From 17c3ced6488eb14a01b39f1ad724fcfcd5d0c4e7 Mon Sep 17 00:00:00 2001 From: Florian Dold Date: Thu, 13 Jan 2022 22:01:14 +0100 Subject: make more use of the denom cache --- packages/taler-wallet-cli/src/harness/harness.ts | 1 + packages/taler-wallet-core/src/common.ts | 2 +- .../taler-wallet-core/src/operations/deposits.ts | 14 +++--- .../taler-wallet-core/src/operations/exchanges.ts | 26 +++++------ packages/taler-wallet-core/src/operations/pay.ts | 21 +++++---- .../taler-wallet-core/src/operations/refresh.ts | 51 +++++++++++++++------- .../taler-wallet-core/src/operations/withdraw.ts | 9 +++- packages/taler-wallet-core/src/util/query.ts | 4 +- packages/taler-wallet-core/src/wallet.ts | 9 +++- 9 files changed, 89 insertions(+), 48 deletions(-) (limited to 'packages') diff --git a/packages/taler-wallet-cli/src/harness/harness.ts b/packages/taler-wallet-cli/src/harness/harness.ts index 35162065d..696a112a2 100644 --- a/packages/taler-wallet-cli/src/harness/harness.ts +++ b/packages/taler-wallet-cli/src/harness/harness.ts @@ -1979,6 +1979,7 @@ export async function runTestWithState( }); await new Promise((resolve, reject) => { rl.question("Press enter to shut down test.", () => { + console.error("Requested shutdown"); resolve(); }); }); diff --git a/packages/taler-wallet-core/src/common.ts b/packages/taler-wallet-core/src/common.ts index 5cbfae4b9..957ba1ca1 100644 --- a/packages/taler-wallet-core/src/common.ts +++ b/packages/taler-wallet-core/src/common.ts @@ -228,7 +228,7 @@ export interface InternalWalletState { getDenomInfo( ws: InternalWalletState, - tx: GetReadWriteAccess<{ + tx: GetReadOnlyAccess<{ denominations: typeof WalletStoresV1.denominations; }>, exchangeBaseUrl: string, diff --git a/packages/taler-wallet-core/src/operations/deposits.ts b/packages/taler-wallet-core/src/operations/deposits.ts index afe8e6f30..40a0af310 100644 --- a/packages/taler-wallet-core/src/operations/deposits.ts +++ b/packages/taler-wallet-core/src/operations/deposits.ts @@ -26,7 +26,6 @@ import { ContractTerms, CreateDepositGroupRequest, CreateDepositGroupResponse, - decodeCrock, DenomKeyType, durationFromSpec, GetFeeForDepositRequest, @@ -250,6 +249,7 @@ async function processDepositGroupImpl( }; } const url = new URL(`coins/${perm.coin_pub}/deposit`, perm.exchange_url); + logger.info(`depositing to ${url}`); const httpResp = await ws.http.postJson(url.href, requestBody); await readSuccessResponseJsonOrThrow(httpResp, codecForDepositSuccess()); await ws.db @@ -616,10 +616,12 @@ export async function getEffectiveDepositAmount( if (!coin) { throw Error("can't calculate deposit amount, coin not found"); } - const denom = await tx.denominations.get([ + const denom = await ws.getDenomInfo( + ws, + tx, coin.exchangeBaseUrl, coin.denomPubHash, - ]); + ); if (!denom) { throw Error("can't find denomination to calculate deposit amount"); } @@ -688,10 +690,12 @@ export async function getTotalFeeForDepositAmount( if (!coin) { throw Error("can't calculate deposit amount, coin not found"); } - const denom = await tx.denominations.get([ + const denom = await ws.getDenomInfo( + ws, + tx, coin.exchangeBaseUrl, coin.denomPubHash, - ]); + ); if (!denom) { throw Error("can't find denomination to calculate deposit amount"); } diff --git a/packages/taler-wallet-core/src/operations/exchanges.ts b/packages/taler-wallet-core/src/operations/exchanges.ts index c14f27656..d73d593e8 100644 --- a/packages/taler-wallet-core/src/operations/exchanges.ts +++ b/packages/taler-wallet-core/src/operations/exchanges.ts @@ -131,7 +131,7 @@ async function handleExchangeUpdateError( exchange.retryInfo.retryCounter++; updateRetryInfoTimeout(exchange.retryInfo); exchange.lastError = err; - await tx.exchanges.put(exchange) + await tx.exchanges.put(exchange); }); if (err) { ws.notify({ type: NotificationType.ExchangeOperationError, error: err }); @@ -527,11 +527,11 @@ async function updateExchangeFromUrlImpl( tosFound !== undefined ? tosFound : await downloadExchangeWithTermsOfService( - baseUrl, - ws.http, - timeout, - "text/plain", - ); + baseUrl, + ws.http, + timeout, + "text/plain", + ); let recoupGroupId: string | undefined = undefined; @@ -589,7 +589,7 @@ async function updateExchangeFromUrlImpl( await tx.exchanges.put(r); await tx.exchangeDetails.put(details); - logger.trace("updating denominations in database"); + logger.info("updating denominations in database"); const currentDenomSet = new Set( keysInfo.currentDenominations.map((x) => x.denomPubHash), ); @@ -750,9 +750,10 @@ export async function getExchangeTrust( if (!exchangeDetails) { throw Error(`exchange ${exchangeInfo.baseUrl} details not available`); } - const exchangeTrustRecord = await tx.exchangesTrustStore.indexes.byExchangeMasterPub.get( - exchangeDetails.masterPublicKey, - ); + const exchangeTrustRecord = + await tx.exchangesTrustStore.indexes.byExchangeMasterPub.get( + exchangeDetails.masterPublicKey, + ); if ( exchangeTrustRecord && exchangeTrustRecord.uids.length > 0 && @@ -762,9 +763,8 @@ export async function getExchangeTrust( } for (const auditor of exchangeDetails.auditors) { - const auditorTrustRecord = await tx.auditorTrust.indexes.byAuditorPub.get( - auditor.auditor_pub, - ); + const auditorTrustRecord = + await tx.auditorTrust.indexes.byAuditorPub.get(auditor.auditor_pub); if (auditorTrustRecord && auditorTrustRecord.uids.length > 0) { isAudited = true; break; diff --git a/packages/taler-wallet-core/src/operations/pay.ts b/packages/taler-wallet-core/src/operations/pay.ts index 89930120d..479ab5e1c 100644 --- a/packages/taler-wallet-core/src/operations/pay.ts +++ b/packages/taler-wallet-core/src/operations/pay.ts @@ -166,8 +166,10 @@ export async function getTotalPaymentCost( .filter((x) => Amounts.isSameCurrency(x.value, pcs.coinContributions[i]), ); - const amountLeft = Amounts.sub(denom.value, pcs.coinContributions[i]) - .amount; + const amountLeft = Amounts.sub( + denom.value, + pcs.coinContributions[i], + ).amount; const refreshCost = getTotalRefreshCost(allDenoms, denom, amountLeft); costs.push(pcs.coinContributions[i]); costs.push(refreshCost); @@ -290,10 +292,12 @@ export async function getCandidatePayCoins( // Denomination of the first coin, we assume that all other // coins have the same currency - const firstDenom = await tx.denominations.get([ + const firstDenom = await ws.getDenomInfo( + ws, + tx, exchange.baseUrl, coins[0].denomPubHash, - ]); + ); if (!firstDenom) { throw Error("db inconsistent"); } @@ -365,6 +369,7 @@ export async function applyCoinSpend( coinSelection: PayCoinSelection, allocationId: string, ) { + logger.info(`applying coin spend ${j2s(coinSelection)}`); for (let i = 0; i < coinSelection.coinPubs.length; i++) { const coin = await tx.coins.get(coinSelection.coinPubs[i]); if (!coin) { @@ -525,7 +530,8 @@ async function incrementPurchasePayRetry( pr.payRetryInfo.retryCounter++; updateRetryInfoTimeout(pr.payRetryInfo); logger.trace( - `retrying pay in ${getDurationRemaining(pr.payRetryInfo.nextRetry).d_ms + `retrying pay in ${ + getDurationRemaining(pr.payRetryInfo.nextRetry).d_ms } ms`, ); pr.lastPayError = err; @@ -812,9 +818,8 @@ async function processDownloadProposalImpl( (fulfillmentUrl.startsWith("http://") || fulfillmentUrl.startsWith("https://")) ) { - const differentPurchase = await tx.purchases.indexes.byFulfillmentUrl.get( - fulfillmentUrl, - ); + const differentPurchase = + await tx.purchases.indexes.byFulfillmentUrl.get(fulfillmentUrl); if (differentPurchase) { logger.warn("repurchase detected"); p.proposalStatus = ProposalStatus.REPURCHASE; diff --git a/packages/taler-wallet-core/src/operations/refresh.ts b/packages/taler-wallet-core/src/operations/refresh.ts index 5b589f1fa..1e5dd68a8 100644 --- a/packages/taler-wallet-core/src/operations/refresh.ts +++ b/packages/taler-wallet-core/src/operations/refresh.ts @@ -67,7 +67,11 @@ import { } from "@gnu-taler/taler-util"; import { guardOperationException } from "../errors.js"; import { updateExchangeFromUrl } from "./exchanges.js"; -import { EXCHANGE_COINS_LOCK, InternalWalletState } from "../common.js"; +import { + DenomInfo, + EXCHANGE_COINS_LOCK, + InternalWalletState, +} from "../common.js"; import { isWithdrawableDenom, selectWithdrawalDenominations, @@ -90,7 +94,7 @@ const logger = new Logger("refresh.ts"); */ export function getTotalRefreshCost( denoms: DenominationRecord[], - refreshedDenom: DenominationRecord, + refreshedDenom: DenomInfo, amountLeft: AmountJson, ): AmountJson { const withdrawAmount = Amounts.sub( @@ -193,10 +197,12 @@ async function refreshCreateSession( denominations: x.denominations, })) .runReadOnly(async (tx) => { - const oldDenom = await tx.denominations.get([ + const oldDenom = await ws.getDenomInfo( + ws, + tx, exchange.baseUrl, coin.denomPubHash, - ]); + ); if (!oldDenom) { throw Error("db inconsistent: denomination for coin not found"); @@ -321,10 +327,12 @@ async function refreshMelt( const oldCoin = await tx.coins.get(refreshGroup.oldCoinPubs[coinIndex]); checkDbInvariant(!!oldCoin, "melt coin doesn't exist"); - const oldDenom = await tx.denominations.get([ + const oldDenom = await ws.getDenomInfo( + ws, + tx, oldCoin.exchangeBaseUrl, oldCoin.denomPubHash, - ]); + ); checkDbInvariant( !!oldDenom, "denomination for melted coin doesn't exist", @@ -333,10 +341,12 @@ async function refreshMelt( const newCoinDenoms: RefreshNewDenomInfo[] = []; for (const dh of refreshSession.newDenoms) { - const newDenom = await tx.denominations.get([ + const newDenom = await ws.getDenomInfo( + ws, + tx, oldCoin.exchangeBaseUrl, dh.denomPubHash, - ]); + ); checkDbInvariant( !!newDenom, "new denomination for refresh not in database", @@ -480,6 +490,7 @@ async function refreshReveal( refreshGroupId: string, coinIndex: number, ): Promise { + logger.info("doing refresh reveal"); const d = await ws.db .mktx((x) => ({ refreshGroups: x.refreshGroups, @@ -502,10 +513,12 @@ async function refreshReveal( const oldCoin = await tx.coins.get(refreshGroup.oldCoinPubs[coinIndex]); checkDbInvariant(!!oldCoin, "melt coin doesn't exist"); - const oldDenom = await tx.denominations.get([ + const oldDenom = await ws.getDenomInfo( + ws, + tx, oldCoin.exchangeBaseUrl, oldCoin.denomPubHash, - ]); + ); checkDbInvariant( !!oldDenom, "denomination for melted coin doesn't exist", @@ -514,10 +527,12 @@ async function refreshReveal( const newCoinDenoms: RefreshNewDenomInfo[] = []; for (const dh of refreshSession.newDenoms) { - const newDenom = await tx.denominations.get([ + const newDenom = await ws.getDenomInfo( + ws, + tx, oldCoin.exchangeBaseUrl, dh.denomPubHash, - ]); + ); checkDbInvariant( !!newDenom, "new denomination for refresh not in database", @@ -794,6 +809,7 @@ async function processRefreshGroupImpl( refreshGroupId: string, forceNow: boolean, ): Promise { + logger.info(`processing refresh group ${refreshGroupId}`); if (forceNow) { await resetRefreshGroupRetry(ws, refreshGroupId); } @@ -823,7 +839,7 @@ async function processRefreshSession( refreshGroupId: string, coinIndex: number, ): Promise { - logger.trace( + logger.info( `processing refresh session for coin ${coinIndex} of group ${refreshGroupId}`, ); let refreshGroup = await ws.db @@ -911,10 +927,12 @@ export async function createRefreshGroup( for (const ocp of oldCoinPubs) { const coin = await tx.coins.get(ocp.coinPub); checkDbInvariant(!!coin, "coin must be in database"); - const denom = await tx.denominations.get([ + const denom = await ws.getDenomInfo( + ws, + tx, coin.exchangeBaseUrl, coin.denomPubHash, - ]); + ); checkDbInvariant( !!denom, "denomination for existing coin must be in database", @@ -949,11 +967,12 @@ export async function createRefreshGroup( if (oldCoinPubs.length == 0) { logger.warn("created refresh group with zero coins"); refreshGroup.timestampFinished = getTimestampNow(); + refreshGroup.operationStatus = OperationStatus.Finished; } await tx.refreshGroups.put(refreshGroup); - logger.trace(`created refresh group ${refreshGroupId}`); + logger.info(`created refresh group ${refreshGroupId}`); processRefreshGroup(ws, refreshGroupId).catch((e) => { logger.warn(`processing refresh group ${refreshGroupId} failed: ${e}`); diff --git a/packages/taler-wallet-core/src/operations/withdraw.ts b/packages/taler-wallet-core/src/operations/withdraw.ts index f9eeb02c0..79220089b 100644 --- a/packages/taler-wallet-core/src/operations/withdraw.ts +++ b/packages/taler-wallet-core/src/operations/withdraw.ts @@ -453,6 +453,9 @@ async function processPlanchetExchangeRequest( withdrawalGroup: WithdrawalGroupRecord, coinIdx: number, ): Promise { + logger.info( + `processing planchet exchange request ${withdrawalGroup.withdrawalGroupId}/${coinIdx}`, + ); const d = await ws.db .mktx((x) => ({ withdrawalGroups: x.withdrawalGroups, @@ -478,10 +481,12 @@ async function processPlanchetExchangeRequest( return; } - const denom = await tx.denominations.get([ + const denom = await ws.getDenomInfo( + ws, + tx, withdrawalGroup.exchangeBaseUrl, planchet.denomPubHash, - ]); + ); if (!denom) { logger.error("db inconsistent: denom for planchet not found"); diff --git a/packages/taler-wallet-core/src/util/query.ts b/packages/taler-wallet-core/src/util/query.ts index 2d0fc077e..e954e5c78 100644 --- a/packages/taler-wallet-core/src/util/query.ts +++ b/packages/taler-wallet-core/src/util/query.ts @@ -333,7 +333,7 @@ export interface StoreReadWriteAccessor { export interface StoreWithIndexes< SD extends StoreDescriptor, - IndexMap + IndexMap, > { store: SD; indexMap: IndexMap; @@ -586,7 +586,7 @@ export class DbAccess { mktx< PickerType extends (x: StoreMap) => unknown, - BoundStores extends GetPickerType + BoundStores extends GetPickerType, >(f: PickerType): TransactionContext { const storePick = f(this.stores) as any; if (typeof storePick !== "object" || storePick === null) { diff --git a/packages/taler-wallet-core/src/wallet.ts b/packages/taler-wallet-core/src/wallet.ts index c5eb0e65c..347a1eb03 100644 --- a/packages/taler-wallet-core/src/wallet.ts +++ b/packages/taler-wallet-core/src/wallet.ts @@ -626,6 +626,7 @@ async function setCoinSuspended( */ async function dumpCoins(ws: InternalWalletState): Promise { const coinsJson: CoinDumpJson = { coins: [] }; + logger.info("dumping coins"); await ws.db .mktx((x) => ({ coins: x.coins, @@ -1206,9 +1207,15 @@ class InternalWalletStateImpl implements InternalWalletState { const key = `${exchangeBaseUrl}:${denomPubHash}`; const cached = this.denomCache[key]; if (cached) { + logger.info("using cached denom"); return cached; } - return await tx.denominations.get([exchangeBaseUrl, denomPubHash]); + logger.info("looking up denom denom"); + const d = await tx.denominations.get([exchangeBaseUrl, denomPubHash]); + if (d) { + this.denomCache[key] = d; + } + return d; } notify(n: WalletNotification): void { -- cgit v1.2.3