diff --git a/packages/taler-wallet-core/src/crypto/workers/cryptoImplementation.ts b/packages/taler-wallet-core/src/crypto/workers/cryptoImplementation.ts index 4195ebded..c39ebb44a 100644 --- a/packages/taler-wallet-core/src/crypto/workers/cryptoImplementation.ts +++ b/packages/taler-wallet-core/src/crypto/workers/cryptoImplementation.ts @@ -29,7 +29,7 @@ import { CoinRecord, DenominationRecord, - RefreshPlanchetRecord, + RefreshPlanchet, RefreshSessionRecord, TipPlanchet, WireFee, @@ -385,7 +385,7 @@ export class CryptoImplementation { const transferPubs: string[] = []; const transferPrivs: string[] = []; - const planchetsForGammas: RefreshPlanchetRecord[][] = []; + const planchetsForGammas: RefreshPlanchet[][] = []; for (let i = 0; i < kappa; i++) { const transferKeyPair = createEcdheKeyPair(); @@ -405,7 +405,7 @@ export class CryptoImplementation { sessionHc.update(amountToBuffer(valueWithFee)); for (let i = 0; i < kappa; i++) { - const planchets: RefreshPlanchetRecord[] = []; + const planchets: RefreshPlanchet[] = []; for (let j = 0; j < newCoinDenoms.selectedDenoms.length; j++) { const denomSel = newCoinDenoms.selectedDenoms[j]; for (let k = 0; k < denomSel.count; k++) { @@ -423,7 +423,7 @@ export class CryptoImplementation { const pubHash = hash(coinPub); const denomPub = decodeCrock(denomSel.denom.denomPub); const ev = rsaBlind(pubHash, blindingFactor, denomPub); - const planchet: RefreshPlanchetRecord = { + const planchet: RefreshPlanchet = { blindingKey: encodeCrock(blindingFactor), coinEv: encodeCrock(ev), privateKey: encodeCrock(coinPriv), diff --git a/packages/taler-wallet-core/src/operations/exchanges.ts b/packages/taler-wallet-core/src/operations/exchanges.ts index d3c72d164..7bf07ab2a 100644 --- a/packages/taler-wallet-core/src/operations/exchanges.ts +++ b/packages/taler-wallet-core/src/operations/exchanges.ts @@ -29,9 +29,6 @@ import { DenominationStatus, WireFee, ExchangeUpdateReason, - ExchangeUpdatedEventRecord, - initRetryInfo, - updateRetryInfoTimeout, } from "../types/dbTypes"; import { canonicalizeBaseUrl } from "../util/helpers"; import * as Amounts from "../util/amounts"; @@ -64,6 +61,7 @@ import { URL } from "../util/url"; import { reconcileReserveHistory } from "../util/reserveHistoryUtil"; import { checkDbInvariant } from "../util/invariants"; import { NotificationType } from "../types/notifications"; +import { updateRetryInfoTimeout, initRetryInfo } from "../util/retries"; const logger = new Logger("exchanges.ts"); @@ -292,7 +290,7 @@ async function updateExchangeFinalize( return; } await ws.db.runWithWriteTransaction( - [Stores.exchanges, Stores.exchangeUpdatedEvents], + [Stores.exchanges], async (tx) => { const r = await tx.get(Stores.exchanges, exchangeBaseUrl); if (!r) { @@ -307,11 +305,6 @@ async function updateExchangeFinalize( // as now new denominations might be available. r.nextRefreshCheck = undefined; await tx.put(Stores.exchanges, r); - const updateEvent: ExchangeUpdatedEventRecord = { - exchangeBaseUrl: exchange.baseUrl, - timestamp: getTimestampNow(), - }; - await tx.put(Stores.exchangeUpdatedEvents, updateEvent); }, ); } @@ -557,7 +550,7 @@ export async function getExchangeTrust( ); if (currencyRecord) { for (const trustedExchange of currencyRecord.exchanges) { - if (trustedExchange.exchangePub === exchangeDetails.masterPublicKey) { + if (trustedExchange.exchangeMasterPub === exchangeDetails.masterPublicKey) { isTrusted = true; break; } diff --git a/packages/taler-wallet-core/src/operations/pay.ts b/packages/taler-wallet-core/src/operations/pay.ts index 50f863e48..c655aa7d8 100644 --- a/packages/taler-wallet-core/src/operations/pay.ts +++ b/packages/taler-wallet-core/src/operations/pay.ts @@ -27,15 +27,11 @@ import { encodeCrock, getRandomBytes } from "../crypto/talerCrypto"; import { CoinStatus, - initRetryInfo, ProposalRecord, ProposalStatus, PurchaseRecord, Stores, - updateRetryInfoTimeout, - PayEventRecord, WalletContractData, - getRetryDuration, CoinRecord, DenominationRecord, } from "../types/dbTypes"; @@ -80,6 +76,7 @@ import { } from "../util/http"; import { TalerErrorCode } from "../TalerErrorCode"; import { URL } from "../util/url"; +import { initRetryInfo, updateRetryInfoTimeout, getRetryDuration } from "../util/retries"; /** * Logger. @@ -833,7 +830,7 @@ async function storeFirstPaySuccess( ): Promise { const now = getTimestampNow(); await ws.db.runWithWriteTransaction( - [Stores.purchases, Stores.payEvents], + [Stores.purchases], async (tx) => { const purchase = await tx.get(Stores.purchases, proposalId); @@ -864,13 +861,6 @@ async function storeFirstPaySuccess( } await tx.put(Stores.purchases, purchase); - const payEvent: PayEventRecord = { - proposalId, - sessionId, - timestamp: now, - isReplay: !isFirst, - }; - await tx.put(Stores.payEvents, payEvent); }, ); } @@ -881,7 +871,7 @@ async function storePayReplaySuccess( sessionId: string | undefined, ): Promise { await ws.db.runWithWriteTransaction( - [Stores.purchases, Stores.payEvents], + [Stores.purchases], async (tx) => { const purchase = await tx.get(Stores.purchases, proposalId); diff --git a/packages/taler-wallet-core/src/operations/recoup.ts b/packages/taler-wallet-core/src/operations/recoup.ts index 3f53d93ed..634869ece 100644 --- a/packages/taler-wallet-core/src/operations/recoup.ts +++ b/packages/taler-wallet-core/src/operations/recoup.ts @@ -34,14 +34,11 @@ import { RefreshCoinSource, ReserveRecordStatus, RecoupGroupRecord, - initRetryInfo, - updateRetryInfoTimeout, } from "../types/dbTypes"; import { codecForRecoupConfirmation } from "../types/talerTypes"; import { NotificationType } from "../types/notifications"; import { - forceQueryReserve, getReserveRequestTimeout, processReserve, } from "./reserves"; @@ -56,6 +53,7 @@ import { guardOperationException } from "./errors"; import { readSuccessResponseJsonOrThrow } from "../util/http"; import { URL } from "../util/url"; import { Logger } from "../util/logging"; +import { initRetryInfo, updateRetryInfoTimeout } from "../util/retries"; const logger = new Logger("operations/recoup.ts"); diff --git a/packages/taler-wallet-core/src/operations/refresh.ts b/packages/taler-wallet-core/src/operations/refresh.ts index a7082a501..a6917c285 100644 --- a/packages/taler-wallet-core/src/operations/refresh.ts +++ b/packages/taler-wallet-core/src/operations/refresh.ts @@ -19,11 +19,9 @@ import { DenominationRecord, Stores, CoinStatus, - RefreshPlanchetRecord, + RefreshPlanchet, CoinRecord, RefreshSessionRecord, - initRetryInfo, - updateRetryInfoTimeout, RefreshGroupRecord, CoinSourceType, } from "../types/dbTypes"; @@ -56,8 +54,6 @@ import { } from "../util/time"; import { readSuccessResponseJsonOrThrow, - HttpResponse, - throwUnexpectedRequestError, } from "../util/http"; import { codecForExchangeMeltResponse, @@ -65,6 +61,7 @@ import { } from "../types/talerTypes"; import { URL } from "../util/url"; import { checkDbInvariant } from "../util/invariants"; +import { initRetryInfo, updateRetryInfoTimeout } from "../util/retries"; const logger = new Logger("refresh.ts"); @@ -326,7 +323,7 @@ async function refreshReveal( throw Error("inconsistent database"); } - const evs = planchets.map((x: RefreshPlanchetRecord) => x.coinEv); + const evs = planchets.map((x: RefreshPlanchet) => x.coinEv); const linkSigs: string[] = []; for (let i = 0; i < refreshSession.newDenoms.length; i++) { diff --git a/packages/taler-wallet-core/src/operations/refund.ts b/packages/taler-wallet-core/src/operations/refund.ts index 0c89e5241..d49675c09 100644 --- a/packages/taler-wallet-core/src/operations/refund.ts +++ b/packages/taler-wallet-core/src/operations/refund.ts @@ -32,8 +32,6 @@ import { } from "../types/walletTypes"; import { Stores, - updateRetryInfoTimeout, - initRetryInfo, CoinStatus, RefundReason, RefundState, @@ -55,6 +53,7 @@ import { Logger } from "../util/logging"; import { readSuccessResponseJsonOrThrow } from "../util/http"; import { TransactionHandle } from "../util/query"; import { URL } from "../util/url"; +import { updateRetryInfoTimeout, initRetryInfo } from "../util/retries"; const logger = new Logger("refund.ts"); @@ -265,7 +264,6 @@ async function acceptRefunds( Stores.coins, Stores.denominations, Stores.refreshGroups, - Stores.refundEvents, ], async (tx) => { const p = await tx.get(Stores.purchases, proposalId); diff --git a/packages/taler-wallet-core/src/operations/reserves.ts b/packages/taler-wallet-core/src/operations/reserves.ts index b4fa3b23e..6db203472 100644 --- a/packages/taler-wallet-core/src/operations/reserves.ts +++ b/packages/taler-wallet-core/src/operations/reserves.ts @@ -28,14 +28,9 @@ import { CurrencyRecord, Stores, WithdrawalGroupRecord, - initRetryInfo, - updateRetryInfoTimeout, - ReserveUpdatedEventRecord, WalletReserveHistoryItemType, - WithdrawalSourceType, ReserveHistoryRecord, ReserveBankInfo, - getRetryDuration, } from "../types/dbTypes"; import { Logger } from "../util/logging"; import { Amounts } from "../util/amounts"; @@ -86,6 +81,7 @@ import { } from "../util/http"; import { codecForAny } from "../util/codec"; import { URL } from "../util/url"; +import { initRetryInfo, getRetryDuration, updateRetryInfoTimeout } from "../util/retries"; const logger = new Logger("reserves.ts"); @@ -206,8 +202,8 @@ export async function createReserve( if (!isAudited && !isTrusted) { currencyRecord.exchanges.push({ - baseUrl: req.exchange, - exchangePub: exchangeDetails.masterPublicKey, + exchangeBaseUrl: req.exchange, + exchangeMasterPub: exchangeDetails.masterPublicKey, }); } @@ -554,7 +550,7 @@ async function updateReserve( const currency = balance.currency; let updateSummary: ReserveHistorySummary | undefined; await ws.db.runWithWriteTransaction( - [Stores.reserves, Stores.reserveUpdatedEvents, Stores.reserveHistory], + [Stores.reserves, Stores.reserveHistory], async (tx) => { const r = await tx.get(Stores.reserves, reservePub); if (!r) { @@ -589,15 +585,6 @@ async function updateReserve( reconciled.newAddedItems.length + reconciled.newMatchedItems.length != 0 ) { - const reserveUpdate: ReserveUpdatedEventRecord = { - reservePub: r.reservePub, - timestamp: getTimestampNow(), - amountReserveBalance: Amounts.stringify(balance), - amountExpected: Amounts.stringify(updateSummary.awaitedReserveAmount), - newHistoryTransactions, - reserveUpdateId, - }; - await tx.put(Stores.reserveUpdatedEvents, reserveUpdate); logger.trace("setting reserve status to 'withdrawing' after query"); r.reserveStatus = ReserveRecordStatus.WITHDRAWING; r.retryInfo = initRetryInfo(); diff --git a/packages/taler-wallet-core/src/operations/tip.ts b/packages/taler-wallet-core/src/operations/tip.ts index 248ea2cd1..7b914568f 100644 --- a/packages/taler-wallet-core/src/operations/tip.ts +++ b/packages/taler-wallet-core/src/operations/tip.ts @@ -25,8 +25,6 @@ import { import * as Amounts from "../util/amounts"; import { Stores, - initRetryInfo, - updateRetryInfoTimeout, TipPlanchet, CoinRecord, CoinSourceType, @@ -47,6 +45,7 @@ import { URL } from "../util/url"; import { Logger } from "../util/logging"; import { checkDbInvariant } from "../util/invariants"; import { TalerErrorCode } from "../TalerErrorCode"; +import { initRetryInfo, updateRetryInfoTimeout } from "../util/retries"; const logger = new Logger("operations/tip.ts"); diff --git a/packages/taler-wallet-core/src/operations/transactions.ts b/packages/taler-wallet-core/src/operations/transactions.ts index 026a91ef3..54d4d5574 100644 --- a/packages/taler-wallet-core/src/operations/transactions.ts +++ b/packages/taler-wallet-core/src/operations/transactions.ts @@ -20,7 +20,6 @@ import { InternalWalletState } from "./state"; import { Stores, - WithdrawalSourceType, WalletRefundItem, RefundState, ReserveRecordStatus, @@ -95,10 +94,7 @@ export async function getTransactions( Stores.reserveHistory, Stores.tips, Stores.withdrawalGroups, - Stores.payEvents, Stores.planchets, - Stores.refundEvents, - Stores.reserveUpdatedEvents, Stores.recoupGroups, ], // Report withdrawals that are currently in progress. diff --git a/packages/taler-wallet-core/src/operations/withdraw.ts b/packages/taler-wallet-core/src/operations/withdraw.ts index eec92ba29..fd472fdfe 100644 --- a/packages/taler-wallet-core/src/operations/withdraw.ts +++ b/packages/taler-wallet-core/src/operations/withdraw.ts @@ -21,12 +21,9 @@ import { DenominationStatus, CoinStatus, CoinRecord, - initRetryInfo, - updateRetryInfoTimeout, CoinSourceType, DenominationSelectionInfo, PlanchetRecord, - WithdrawalSourceType, DenomSelectionState, } from "../types/dbTypes"; import { @@ -64,6 +61,7 @@ import { readSuccessResponseJsonOrThrow } from "../util/http"; import { URL } from "../util/url"; import { TalerErrorCode } from "../TalerErrorCode"; import { encodeCrock } from "../crypto/talerCrypto"; +import { updateRetryInfoTimeout, initRetryInfo } from "../util/retries"; const logger = new Logger("withdraw.ts"); diff --git a/packages/taler-wallet-core/src/types/dbTypes.ts b/packages/taler-wallet-core/src/types/dbTypes.ts index 60a427ef2..0074409e8 100644 --- a/packages/taler-wallet-core/src/types/dbTypes.ts +++ b/packages/taler-wallet-core/src/types/dbTypes.ts @@ -46,6 +46,7 @@ import { import { Timestamp, Duration, getTimestampNow } from "../util/time"; import { PayCoinSelection, PayCostInfo } from "../operations/pay"; import { IDBKeyPath } from "idb-bridge"; +import { RetryInfo } from "../util/retries"; export enum ReserveRecordStatus { /** @@ -84,74 +85,6 @@ export enum ReserveRecordStatus { BANK_ABORTED = "bank-aborted", } -export interface RetryInfo { - firstTry: Timestamp; - nextRetry: Timestamp; - retryCounter: number; - active: boolean; -} - -export interface RetryPolicy { - readonly backoffDelta: Duration; - readonly backoffBase: number; -} - -const defaultRetryPolicy: RetryPolicy = { - backoffBase: 1.5, - backoffDelta: { d_ms: 200 }, -}; - -export function updateRetryInfoTimeout( - r: RetryInfo, - p: RetryPolicy = defaultRetryPolicy, -): void { - const now = getTimestampNow(); - if (now.t_ms === "never") { - throw Error("assertion failed"); - } - if (p.backoffDelta.d_ms === "forever") { - r.nextRetry = { t_ms: "never" }; - return; - } - r.active = true; - const t = - now.t_ms + p.backoffDelta.d_ms * Math.pow(p.backoffBase, r.retryCounter); - r.nextRetry = { t_ms: t }; -} - -export function getRetryDuration( - r: RetryInfo, - p: RetryPolicy = defaultRetryPolicy, -): Duration { - if (p.backoffDelta.d_ms === "forever") { - return { d_ms: "forever" }; - } - const t = p.backoffDelta.d_ms * Math.pow(p.backoffBase, r.retryCounter); - return { d_ms: t }; -} - -export function initRetryInfo( - active = true, - p: RetryPolicy = defaultRetryPolicy, -): RetryInfo { - if (!active) { - return { - active: false, - firstTry: { t_ms: Number.MAX_SAFE_INTEGER }, - nextRetry: { t_ms: Number.MAX_SAFE_INTEGER }, - retryCounter: 0, - }; - } - const info = { - firstTry: getTimestampNow(), - active: true, - nextRetry: { t_ms: 0 }, - retryCounter: 0, - }; - updateRetryInfoTimeout(info, p); - return info; -} - export enum WalletReserveHistoryItemType { Credit = "credit", Withdraw = "withdraw", @@ -353,10 +286,12 @@ export interface AuditorRecord { * Base url of the auditor. */ baseUrl: string; + /** * Public signing key of the auditor. */ auditorPub: string; + /** * Time when the auditing expires. */ @@ -371,11 +306,12 @@ export interface ExchangeForCurrencyRecord { /** * FIXME: unused? */ - exchangePub: string; + exchangeMasterPub: string; + /** * Base URL of the exchange. */ - baseUrl: string; + exchangeBaseUrl: string; } /** @@ -386,14 +322,17 @@ export interface CurrencyRecord { * Name of the currency. */ name: string; + /** * Number of fractional digits to show when rendering the currency. */ fractionalDigits: number; + /** * Auditors that the wallet trusts for this currency. */ auditors: AuditorRecord[]; + /** * Exchanges that the wallet trusts for this currency. */ @@ -722,7 +661,7 @@ export interface PlanchetRecord { /** * Planchet for a coin during refrehs. */ -export interface RefreshPlanchetRecord { +export interface RefreshPlanchet { /** * Public key for the coin. */ @@ -1083,7 +1022,7 @@ export interface RefreshSessionRecord { /** * Planchets for each cut-and-choose instance. */ - planchetsForGammas: RefreshPlanchetRecord[][]; + planchetsForGammas: RefreshPlanchet[][]; /** * The transfer keys, kappa of them. @@ -1431,54 +1370,6 @@ export interface ConfigRecord { value: any; } -/** - * Coin that we're depositing ourselves. - */ -export interface DepositCoin { - coinPaySig: CoinDepositPermission; - - /** - * Undefined if coin not deposited, otherwise signature - * from the exchange confirming the deposit. - */ - depositedSig?: string; -} - -/** - * Record stored in the wallet's database when the user sends coins back to - * their own bank account. Stores the status of coins that are deposited to - * the wallet itself, where the wallet acts as a "merchant" for the customer. - */ -export interface CoinsReturnRecord { - contractTermsRaw: string; - - contractData: WalletContractData; - - /** - * Private key where corresponding - * public key is used in the contract terms - * as merchant pub. - */ - merchantPriv: string; - - coins: DepositCoin[]; - - /** - * Exchange base URL to deposit coins at. - */ - exchange: string; - - /** - * Our own wire information for the deposit. - */ - wire: any; -} - -export enum WithdrawalSourceType { - Tip = "tip", - Reserve = "reserve", -} - export interface DenominationSelectionInfo { totalCoinValue: AmountJson; totalWithdrawCost: AmountJson; @@ -1610,31 +1501,6 @@ export enum ImportPayloadType { CoreSchema = "core-schema", } -/** - * Record to keep track of data imported into the wallet. - */ -export class WalletImportRecord { - /** - * Unique ID to reference this import record. - */ - walletImportId: string; - - /** - * When was the data imported? - */ - timestampImportStarted: Timestamp; - - timestampImportFinished: Timestamp | undefined; - - payloadType: ImportPayloadType; - - /** - * The actual data to import. - */ - payload: any; -} - -/* tslint:disable:completed-docs */ class ExchangesStore extends Store { constructor() { @@ -1773,51 +1639,21 @@ class PlanchetsStore extends Store { ); } -class RefundEventsStore extends Store { - constructor() { - super("refundEvents", { keyPath: "refundGroupId" }); - } -} - -class PayEventsStore extends Store { - constructor() { - super("payEvents", { keyPath: "proposalId" }); - } -} - -class ExchangeUpdatedEventsStore extends Store { - constructor() { - super("exchangeUpdatedEvents", { keyPath: "exchangeBaseUrl" }); - } -} - -class ReserveUpdatedEventsStore extends Store { - constructor() { - super("reserveUpdatedEvents", { keyPath: "reservePub" }); - } -} - +/** + * This store is effectively a materialized index for + * reserve records that are for a bank-integrated withdrawal. + */ class BankWithdrawUrisStore extends Store { constructor() { super("bankWithdrawUris", { keyPath: "talerWithdrawUri" }); } } -class WalletImportsStore extends Store { - constructor() { - super("walletImports", { keyPath: "walletImportId" }); - } -} - /** * The stores and indices for the wallet database. */ - export const Stores = { coins: new CoinsStore(), - coinsReturns: new Store("coinsReturns", { - keyPath: "contractTermsHash", - }), config: new ConfigStore(), currencies: new CurrenciesStore(), denominations: new DenominationsStore(), @@ -1837,11 +1673,4 @@ export const Stores = { withdrawalGroups: new WithdrawalGroupsStore(), planchets: new PlanchetsStore(), bankWithdrawUris: new BankWithdrawUrisStore(), - refundEvents: new RefundEventsStore(), - payEvents: new PayEventsStore(), - reserveUpdatedEvents: new ReserveUpdatedEventsStore(), - exchangeUpdatedEvents: new ExchangeUpdatedEventsStore(), - walletImports: new WalletImportsStore(), }; - -/* tslint:enable:completed-docs */ diff --git a/packages/taler-wallet-core/src/types/pending.ts b/packages/taler-wallet-core/src/types/pending.ts index b14872d74..18d9a2fa4 100644 --- a/packages/taler-wallet-core/src/types/pending.ts +++ b/packages/taler-wallet-core/src/types/pending.ts @@ -22,8 +22,9 @@ * Imports. */ import { TalerErrorDetails, BalancesResponse } from "./walletTypes"; -import { RetryInfo, ReserveRecordStatus } from "./dbTypes"; +import { ReserveRecordStatus } from "./dbTypes"; import { Timestamp, Duration } from "../util/time"; +import { RetryInfo } from "../util/retries"; export enum PendingOperationType { Bug = "bug",