From 957f9a5efb26194a7911cdaf722502ba09e5bd58 Mon Sep 17 00:00:00 2001 From: Florian Dold Date: Wed, 5 Oct 2022 18:31:56 +0200 Subject: wallet-core: fix default auditor/exchange loading logic --- .../src/crypto/workers/worker-common.ts | 1 - packages/taler-wallet-core/src/db.ts | 6 ++- .../src/operations/backup/import.ts | 2 + .../taler-wallet-core/src/operations/exchanges.ts | 59 ++++++++++++---------- .../taler-wallet-core/src/operations/pending.ts | 1 + .../taler-wallet-core/src/operations/withdraw.ts | 21 ++++---- packages/taler-wallet-core/src/wallet.ts | 45 ++++++++--------- 7 files changed, 70 insertions(+), 65 deletions(-) (limited to 'packages/taler-wallet-core') diff --git a/packages/taler-wallet-core/src/crypto/workers/worker-common.ts b/packages/taler-wallet-core/src/crypto/workers/worker-common.ts index dae6d1e28..459033526 100644 --- a/packages/taler-wallet-core/src/crypto/workers/worker-common.ts +++ b/packages/taler-wallet-core/src/crypto/workers/worker-common.ts @@ -37,7 +37,6 @@ export async function processRequestWithImpl( reqMsg: CryptoWorkerRequestMessage, impl: TalerCryptoInterfaceR, ): Promise { - logger.info(`processing crypto request ${j2s(reqMsg)}`); if (typeof reqMsg !== "object") { logger.error("request must be an object"); return { diff --git a/packages/taler-wallet-core/src/db.ts b/packages/taler-wallet-core/src/db.ts index f8fddb255..16ae2cf8d 100644 --- a/packages/taler-wallet-core/src/db.ts +++ b/packages/taler-wallet-core/src/db.ts @@ -510,7 +510,7 @@ export interface ExchangeRecord { permanent: boolean; /** - * Last time when the exchange was updated. + * Last time when the exchange was updated (both /keys and /wire). */ lastUpdate: TalerProtocolTimestamp | undefined; @@ -521,6 +521,10 @@ export interface ExchangeRecord { */ nextUpdate: TalerProtocolTimestamp; + lastKeysEtag: string | undefined; + + lastWireEtag: string | undefined; + /** * Next time that we should check if coins need to be refreshed. * diff --git a/packages/taler-wallet-core/src/operations/backup/import.ts b/packages/taler-wallet-core/src/operations/backup/import.ts index 9997dd09d..fb747ef1c 100644 --- a/packages/taler-wallet-core/src/operations/backup/import.ts +++ b/packages/taler-wallet-core/src/operations/backup/import.ts @@ -362,6 +362,8 @@ export async function importBackup( lastUpdate: undefined, nextUpdate: TalerProtocolTimestamp.now(), nextRefreshCheck: TalerProtocolTimestamp.now(), + lastKeysEtag: undefined, + lastWireEtag: undefined, }); } diff --git a/packages/taler-wallet-core/src/operations/exchanges.ts b/packages/taler-wallet-core/src/operations/exchanges.ts index 82222a5c4..60a4e91dd 100644 --- a/packages/taler-wallet-core/src/operations/exchanges.ts +++ b/packages/taler-wallet-core/src/operations/exchanges.ts @@ -63,7 +63,11 @@ import { readSuccessResponseJsonOrThrow, readSuccessResponseTextOrThrow, } from "../util/http.js"; -import { DbAccess, GetReadOnlyAccess } from "../util/query.js"; +import { + DbAccess, + GetReadOnlyAccess, + GetReadWriteAccess, +} from "../util/query.js"; import { OperationAttemptResult, OperationAttemptResultType, @@ -316,33 +320,35 @@ async function downloadExchangeWireInfo( return wireInfo; } -async function provideExchangeRecord( +export async function provideExchangeRecordInTx( ws: InternalWalletState, + tx: GetReadWriteAccess<{ + exchanges: typeof WalletStoresV1.exchanges; + exchangeDetails: typeof WalletStoresV1.exchangeDetails; + }>, baseUrl: string, now: AbsoluteTime, ): Promise<{ exchange: ExchangeRecord; exchangeDetails: ExchangeDetailsRecord | undefined; }> { - return await ws.db - .mktx((x) => [x.exchanges, x.exchangeDetails]) - .runReadWrite(async (tx) => { - let exchange = await tx.exchanges.get(baseUrl); - if (!exchange) { - const r: ExchangeRecord = { - permanent: true, - baseUrl: baseUrl, - detailsPointer: undefined, - lastUpdate: undefined, - nextUpdate: AbsoluteTime.toTimestamp(now), - nextRefreshCheck: AbsoluteTime.toTimestamp(now), - }; - await tx.exchanges.put(r); - exchange = r; - } - const exchangeDetails = await getExchangeDetails(tx, baseUrl); - return { exchange, exchangeDetails }; - }); + let exchange = await tx.exchanges.get(baseUrl); + if (!exchange) { + const r: ExchangeRecord = { + permanent: true, + baseUrl: baseUrl, + detailsPointer: undefined, + lastUpdate: undefined, + nextUpdate: AbsoluteTime.toTimestamp(now), + nextRefreshCheck: AbsoluteTime.toTimestamp(now), + lastKeysEtag: undefined, + lastWireEtag: undefined, + }; + await tx.exchanges.put(r); + exchange = r; + } + const exchangeDetails = await getExchangeDetails(tx, baseUrl); + return { exchange, exchangeDetails }; } interface ExchangeKeysDownloadResult { @@ -499,15 +505,16 @@ export async function updateExchangeFromUrlHandler( > { const forceNow = options.forceNow ?? false; logger.info(`updating exchange info for ${baseUrl}, forced: ${forceNow}`); + console.trace("here"); const now = AbsoluteTime.now(); baseUrl = canonicalizeBaseUrl(baseUrl); - const { exchange, exchangeDetails } = await provideExchangeRecord( - ws, - baseUrl, - now, - ); + const { exchange, exchangeDetails } = await ws.db + .mktx((x) => [x.exchanges, x.exchangeDetails]) + .runReadWrite(async (tx) => { + return provideExchangeRecordInTx(ws, tx, baseUrl, now); + }); if ( !forceNow && diff --git a/packages/taler-wallet-core/src/operations/pending.ts b/packages/taler-wallet-core/src/operations/pending.ts index 0dcd09e25..156feadbb 100644 --- a/packages/taler-wallet-core/src/operations/pending.ts +++ b/packages/taler-wallet-core/src/operations/pending.ts @@ -50,6 +50,7 @@ async function gatherExchangePending( now: AbsoluteTime, resp: PendingOperationsResponse, ): Promise { + // FIXME: We should do a range query here based on the update time. await tx.exchanges.iter().forEachAsync(async (exch) => { const opTag = RetryTags.forExchangeUpdate(exch); let opr = await tx.operationRetries.get(opTag); diff --git a/packages/taler-wallet-core/src/operations/withdraw.ts b/packages/taler-wallet-core/src/operations/withdraw.ts index 143f9ce33..d768bbeb2 100644 --- a/packages/taler-wallet-core/src/operations/withdraw.ts +++ b/packages/taler-wallet-core/src/operations/withdraw.ts @@ -1071,7 +1071,7 @@ export async function processWithdrawalGroup( case WithdrawalGroupStatus.QueryingStatus: { const doQueryAsync = async () => { if (ws.stopped) { - logger.info("not long-polling reserve, wallet already stopped"); + logger.trace("not long-polling reserve, wallet already stopped"); await storeOperationPending(ws, retryTag); return; } @@ -1080,7 +1080,7 @@ export async function processWithdrawalGroup( try { ws.activeLongpoll[retryTag] = { cancel: () => { - logger.info("cancel of reserve longpoll requested"); + logger.trace("cancel of reserve longpoll requested"); cts.cancel(); }, }; @@ -1094,16 +1094,13 @@ export async function processWithdrawalGroup( return; } delete ws.activeLongpoll[retryTag]; - logger.info( - `active longpoll keys (2) ${Object.keys(ws.activeLongpoll)}`, - ); if (!res.ready) { await storeOperationPending(ws, retryTag); } ws.latch.trigger(); }; doQueryAsync(); - logger.info( + logger.trace( "returning early from withdrawal for long-polling in background", ); return { @@ -1918,12 +1915,12 @@ export async function acceptWithdrawalFromUri( ); } - // Start withdrawal in the background. - await processWithdrawalGroup(ws, withdrawalGroupId, { forceNow: true }).catch( - (err) => { - logger.error("Processing withdrawal (after creation) failed:", err); - }, - ); + // Start withdrawal in the background + processWithdrawalGroup(ws, withdrawalGroupId, { + forceNow: true, + }).catch((err) => { + logger.error("Processing withdrawal (after creation) failed:", err); + }); return { reservePub: withdrawalGroup.reservePub, diff --git a/packages/taler-wallet-core/src/wallet.ts b/packages/taler-wallet-core/src/wallet.ts index 129ee458f..61525e476 100644 --- a/packages/taler-wallet-core/src/wallet.ts +++ b/packages/taler-wallet-core/src/wallet.ts @@ -155,6 +155,7 @@ import { getExchangeDetails, getExchangeRequestTimeout, getExchangeTrust, + provideExchangeRecordInTx, updateExchangeFromUrl, updateExchangeFromUrlHandler, updateExchangeTermsOfService, @@ -583,32 +584,26 @@ async function runTaskLoop( */ async function fillDefaults(ws: InternalWalletState): Promise { await ws.db - .mktx((x) => [x.config, x.auditorTrust]) + .mktx((x) => [x.config, x.auditorTrust, x.exchanges, x.exchangeDetails]) .runReadWrite(async (tx) => { - let applied = false; - await tx.config.iter().forEach((x) => { - if (x.key == "currencyDefaultsApplied" && x.value == true) { - applied = true; - } - }); - if (!applied) { - for (const c of builtinAuditors) { - await tx.auditorTrust.put(c); - } + const appliedRec = await tx.config.get("currencyDefaultsApplied"); + let alreadyApplied = appliedRec ? !!appliedRec.value : false; + if (alreadyApplied) { + logger.info("defaults already applied"); + return; + } + for (const c of builtinAuditors) { + await tx.auditorTrust.put(c); + } + for (const baseUrl of builtinExchanges) { + const now = AbsoluteTime.now(); + provideExchangeRecordInTx(ws, tx, baseUrl, now); } - // FIXME: make sure exchanges are added transactionally to - // DB in first-time default application + await tx.config.put({ + key: "currencyDefaultsApplied", + value: true, + }); }); - - for (const url of builtinExchanges) { - try { - await updateExchangeFromUrl(ws, url, { forceNow: true }); - } catch (e) { - logger.warn( - `could not update builtin exchange ${url} during wallet initialization`, - ); - } - } } async function getExchangeTos( @@ -1719,12 +1714,12 @@ class InternalWalletStateImpl implements InternalWalletState { * Stop ongoing processing. */ stop(): void { - logger.info("stopping (at internal wallet state)"); + logger.trace("stopping (at internal wallet state)"); this.stopped = true; this.timerGroup.stopCurrentAndFutureTimers(); this.cryptoDispatcher.stop(); for (const key of Object.keys(this.activeLongpoll)) { - logger.info(`cancelling active longpoll ${key}`); + logger.trace(`cancelling active longpoll ${key}`); this.activeLongpoll[key].cancel(); } } -- cgit v1.2.3