From 4fdcaab6325289fd8525fc9e63c8c86b07131376 Mon Sep 17 00:00:00 2001 From: Florian Dold Date: Wed, 12 May 2021 14:16:01 +0200 Subject: model more backup provider errors --- packages/taler-util/src/backupTypes.ts | 5 ++ packages/taler-wallet-core/src/db.ts | 39 ++++++++++++---- .../src/operations/backup/export.ts | 1 + .../src/operations/backup/index.ts | 54 ++++++++++++++++++---- 4 files changed, 81 insertions(+), 18 deletions(-) diff --git a/packages/taler-util/src/backupTypes.ts b/packages/taler-util/src/backupTypes.ts index 13ff75190..1980bfb4e 100644 --- a/packages/taler-util/src/backupTypes.ts +++ b/packages/taler-util/src/backupTypes.ts @@ -304,6 +304,11 @@ export class BackupBackupProvider { * Proposal IDs for payments to this provider. */ pay_proposal_ids: string[]; + + /** + * UIDs for adding this backup provider. + */ + uids: OperationUid[]; } /** diff --git a/packages/taler-wallet-core/src/db.ts b/packages/taler-wallet-core/src/db.ts index 22cbd16cc..946e71e10 100644 --- a/packages/taler-wallet-core/src/db.ts +++ b/packages/taler-wallet-core/src/db.ts @@ -13,7 +13,22 @@ import { IDBKeyPath, } from "@gnu-taler/idb-bridge"; import { Logger } from "./util/logging"; -import { AmountJson, AmountString, Auditor, CoinDepositPermission, ContractTerms, Duration, ExchangeSignKeyJson, InternationalizedString, MerchantInfo, Product, RefreshReason, ReserveTransaction, TalerErrorDetails, Timestamp } from "@gnu-taler/taler-util"; +import { + AmountJson, + AmountString, + Auditor, + CoinDepositPermission, + ContractTerms, + Duration, + ExchangeSignKeyJson, + InternationalizedString, + MerchantInfo, + Product, + RefreshReason, + ReserveTransaction, + TalerErrorDetails, + Timestamp, +} from "@gnu-taler/taler-util"; import { RetryInfo } from "./util/retries.js"; import { PayCoinSelection } from "./util/coinSelection.js"; @@ -170,7 +185,6 @@ export function deleteTalerDatabase(idbFactory: IDBFactory): void { Database.deleteDatabase(idbFactory, TALER_DB_NAME); } - export enum ReserveRecordStatus { /** * Reserve must be registered with the bank. @@ -1269,14 +1283,12 @@ export interface WalletContractData { maxDepositFee: AmountJson; } - export enum AbortStatus { None = "none", AbortRefund = "abort-refund", AbortFinished = "abort-finished", } - /** * Record that stores status information about one purchase, starting from when * the customer accepts a proposal. Includes refund status if applicable. @@ -1316,7 +1328,7 @@ export interface PurchaseRecord { /** * Pending removals from pay coin selection. - * + * * Used when a the pay coin selection needs to be changed * because a coin became known as double-spent or invalid, * but a new coin selection can't immediately be done, as @@ -1548,6 +1560,12 @@ export enum BackupProviderStatus { Ready = "ready", } +export interface BackupProviderTerms { + supportedProtocolVersion: string; + annualFee: AmountString; + storageLimitInMegabytes: number; +} + export interface BackupProviderRecord { baseUrl: string; @@ -1556,11 +1574,7 @@ export interface BackupProviderRecord { * Might be unavailable in the DB in certain situations * (such as loading a recovery document). */ - terms?: { - supportedProtocolVersion: string; - annualFee: AmountString; - storageLimitInMegabytes: number; - }; + terms?: BackupProviderTerms; active: boolean; @@ -1601,6 +1615,11 @@ export interface BackupProviderRecord { * Last error that occurred, if any. */ lastError: TalerErrorDetails | undefined; + + /** + * UIDs for the operation that added the backup provider. + */ + uids: string[]; } /** diff --git a/packages/taler-wallet-core/src/operations/backup/export.ts b/packages/taler-wallet-core/src/operations/backup/export.ts index 4ccaf8f42..70d249ab8 100644 --- a/packages/taler-wallet-core/src/operations/backup/export.ts +++ b/packages/taler-wallet-core/src/operations/backup/export.ts @@ -191,6 +191,7 @@ export async function exportBackup( terms, base_url: canonicalizeBaseUrl(bp.baseUrl), pay_proposal_ids: bp.paymentProposalIds, + uids: bp.uids, }); }); diff --git a/packages/taler-wallet-core/src/operations/backup/index.ts b/packages/taler-wallet-core/src/operations/backup/index.ts index b4c1a6c92..110e76596 100644 --- a/packages/taler-wallet-core/src/operations/backup/index.ts +++ b/packages/taler-wallet-core/src/operations/backup/index.ts @@ -31,8 +31,12 @@ import { codecForAmountString, WalletBackupContentV1, } from "@gnu-taler/taler-util"; -import { TransactionHandle } from "../../util/query"; -import { BackupProviderRecord, ConfigRecord, Stores } from "../../db.js"; +import { + BackupProviderRecord, + BackupProviderTerms, + ConfigRecord, + Stores, +} from "../../db.js"; import { checkDbInvariant, checkLogicInvariant } from "../../util/invariants"; import { bytesToString, @@ -40,13 +44,13 @@ import { eddsaGetPublic, EddsaKeyPair, encodeCrock, + getRandomBytes, hash, rsaBlind, stringToBytes, } from "../../crypto/talerCrypto"; import { canonicalizeBaseUrl, canonicalJson, j2s } from "@gnu-taler/taler-util"; import { - durationAdd, durationFromSpec, getTimestampNow, Timestamp, @@ -495,6 +499,7 @@ export async function addBackupProvider( baseUrl: canonUrl, lastError: undefined, retryInfo: initRetryInfo(false), + uids: [encodeCrock(getRandomBytes(32))], }); } @@ -513,14 +518,39 @@ export async function restoreFromRecoverySecret(): Promise {} export interface ProviderInfo { active: boolean; syncProviderBaseUrl: string; + terms?: BackupProviderTerms; + /** + * Last communication issue with the provider. + */ lastError?: TalerErrorDetails; - lastRemoteClock?: number; - lastBackupTimestamp?: Timestamp; + lastSuccessfulBackupTimestamp?: Timestamp; + lastAttemptedBackupTimestamp?: Timestamp; paymentProposalIds: string[]; + backupProblem?: BackupProblem; paymentStatus: ProviderPaymentStatus; } +export type BackupProblem = + | BackupUnreadableProblem + | BackupConflictingDeviceProblem; + +export interface BackupUnreadableProblem { + type: "backup-unreadable"; +} + +export interface BackupUnreadableProblem { + type: "backup-unreadable"; +} + +export interface BackupConflictingDeviceProblem { + type: "backup-conflicting-device"; + otherDeviceId: string; + myDeviceId: string; + backupTimestamp: Timestamp; +} + export type ProviderPaymentStatus = + | ProviderPaymentTermsChanged | ProviderPaymentPaid | ProviderPaymentInsufficientBalance | ProviderPaymentUnpaid @@ -529,7 +559,6 @@ export type ProviderPaymentStatus = export interface BackupInfo { walletRootPub: string; deviceId: string; - lastLocalClock: number; providers: ProviderInfo[]; } @@ -550,6 +579,7 @@ export enum ProviderPaymentType { Pending = "pending", InsufficientBalance = "insufficient-balance", Paid = "paid", + TermsChanged = "terms-changed", } export interface ProviderPaymentUnpaid { @@ -569,6 +599,13 @@ export interface ProviderPaymentPaid { paidUntil: Timestamp; } +export interface ProviderPaymentTermsChanged { + type: ProviderPaymentType.TermsChanged; + paidUntil: Timestamp; + oldTerms: BackupProviderTerms; + newTerms: BackupProviderTerms; +} + async function getProviderPaymentInfo( ws: InternalWalletState, provider: BackupProviderRecord, @@ -623,15 +660,15 @@ export async function getBackupInfo( providers.push({ active: x.active, syncProviderBaseUrl: x.baseUrl, - lastBackupTimestamp: x.lastBackupTimestamp, + lastSuccessfulBackupTimestamp: x.lastBackupTimestamp, paymentProposalIds: x.paymentProposalIds, lastError: x.lastError, paymentStatus: await getProviderPaymentInfo(ws, x), + terms: x.terms, }); } return { deviceId: backupConfig.deviceId, - lastLocalClock: backupConfig.clocks[backupConfig.deviceId], walletRootPub: backupConfig.walletRootPub, providers, }; @@ -686,6 +723,7 @@ async function backupRecoveryTheirs( paymentProposalIds: [], retryInfo: initRetryInfo(false), lastError: undefined, + uids: [encodeCrock(getRandomBytes(32))], }); } } -- cgit v1.2.3