backup schema
This commit is contained in:
parent
c27a7abfba
commit
80a0fab126
@ -54,7 +54,7 @@ import {
|
|||||||
stringToBytes,
|
stringToBytes,
|
||||||
} from "../crypto/talerCrypto";
|
} from "../crypto/talerCrypto";
|
||||||
import { canonicalizeBaseUrl, canonicalJson, j2s } from "../util/helpers";
|
import { canonicalizeBaseUrl, canonicalJson, j2s } from "../util/helpers";
|
||||||
import { Timestamp } from "../util/time";
|
import { getTimestampNow, Timestamp } from "../util/time";
|
||||||
import { URL } from "../util/url";
|
import { URL } from "../util/url";
|
||||||
import { AmountString } from "../types/talerTypes";
|
import { AmountString } from "../types/talerTypes";
|
||||||
import {
|
import {
|
||||||
@ -77,6 +77,16 @@ interface WalletBackupConfState {
|
|||||||
walletRootPriv: string;
|
walletRootPriv: string;
|
||||||
clocks: { [device_id: string]: number };
|
clocks: { [device_id: string]: number };
|
||||||
lastBackupHash?: string;
|
lastBackupHash?: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Timestamp stored in the last backup.
|
||||||
|
*/
|
||||||
|
lastBackupTimestamp?: Timestamp;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Last time we tried to do a backup.
|
||||||
|
*/
|
||||||
|
lastBackupCheckTimestamp?: Timestamp;
|
||||||
lastBackupNonce?: string;
|
lastBackupNonce?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -237,6 +247,7 @@ export async function exportBackup(
|
|||||||
base_url: ex.baseUrl,
|
base_url: ex.baseUrl,
|
||||||
accounts: ex.wireInfo.accounts.map((x) => ({
|
accounts: ex.wireInfo.accounts.map((x) => ({
|
||||||
payto_uri: x.payto_uri,
|
payto_uri: x.payto_uri,
|
||||||
|
master_sig: x.master_sig,
|
||||||
})),
|
})),
|
||||||
auditors: ex.details.auditors.map((x) => ({
|
auditors: ex.details.auditors.map((x) => ({
|
||||||
auditor_pub: x.auditor_pub,
|
auditor_pub: x.auditor_pub,
|
||||||
@ -261,6 +272,10 @@ export async function exportBackup(
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
if (!bs.lastBackupTimestamp) {
|
||||||
|
bs.lastBackupTimestamp = getTimestampNow();
|
||||||
|
}
|
||||||
|
|
||||||
const backupBlob: WalletBackupContentV1 = {
|
const backupBlob: WalletBackupContentV1 = {
|
||||||
schema_id: "gnu-taler-wallet-backup-content",
|
schema_id: "gnu-taler-wallet-backup-content",
|
||||||
schema_version: 1,
|
schema_version: 1,
|
||||||
@ -275,6 +290,10 @@ export async function exportBackup(
|
|||||||
recoup_groups: [],
|
recoup_groups: [],
|
||||||
refresh_groups: [],
|
refresh_groups: [],
|
||||||
tips: [],
|
tips: [],
|
||||||
|
timestamp: bs.lastBackupTimestamp,
|
||||||
|
trusted_auditors: {},
|
||||||
|
trusted_exchanges: {},
|
||||||
|
intern_table: {},
|
||||||
};
|
};
|
||||||
|
|
||||||
// If the backup changed, we increment our clock.
|
// If the backup changed, we increment our clock.
|
||||||
|
@ -50,6 +50,21 @@ import {
|
|||||||
*/
|
*/
|
||||||
type BackupAmountString = string;
|
type BackupAmountString = string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A human-recognizable identifier here that is
|
||||||
|
* reasonable unique and assigned the first time the wallet is
|
||||||
|
* started/installed, such as:
|
||||||
|
*
|
||||||
|
* `${wallet-implementation} ${os} ${hostname} (${short-uid})`
|
||||||
|
* => e.g. "GNU Taler Android iceking ABC123"
|
||||||
|
*/
|
||||||
|
type DeviceIdString = string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Integer-valued clock.
|
||||||
|
*/
|
||||||
|
type ClockValue = number;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Content of the backup.
|
* Content of the backup.
|
||||||
*
|
*
|
||||||
@ -76,21 +91,29 @@ export interface WalletBackupContentV1 {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Current device identifier that "owns" the backup.
|
* Current device identifier that "owns" the backup.
|
||||||
*
|
*
|
||||||
* This identifier allows one wallet to notice when another
|
* This identifier allows one wallet to notice when another
|
||||||
* wallet is "alive" and connected to the same sync provider.
|
* wallet is "alive" and connected to the same sync provider.
|
||||||
*/
|
*/
|
||||||
current_device_id: string;
|
current_device_id: DeviceIdString;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Monotonically increasing clock of the wallet,
|
* Monotonically increasing clock of the wallet,
|
||||||
* used to determine causality when merging backups.
|
* used to determine causality when merging backups.
|
||||||
*
|
*
|
||||||
* Information about other clocks, used to delete
|
* Information about other clocks, used to delete
|
||||||
* tombstones in the hopefully rare case that multiple wallets
|
* tombstones in the hopefully rare case that multiple wallets
|
||||||
* are connected to the same sync server.
|
* are connected to the same sync server.
|
||||||
*/
|
*/
|
||||||
clocks: { [device_id: string]: number };
|
clocks: { [device_id: string]: ClockValue };
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Timestamp of the backup.
|
||||||
|
*
|
||||||
|
* This timestamp should only be advanced if the content
|
||||||
|
* of the backup changes.
|
||||||
|
*/
|
||||||
|
timestamp: Timestamp;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Per-exchange data sorted by exchange master public key.
|
* Per-exchange data sorted by exchange master public key.
|
||||||
@ -155,6 +178,94 @@ export interface WalletBackupContentV1 {
|
|||||||
*/
|
*/
|
||||||
proposal_id: string;
|
proposal_id: string;
|
||||||
}[];
|
}[];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Trusted auditors, either for official (3 letter) or local (4-12 letter)
|
||||||
|
* currencies.
|
||||||
|
*
|
||||||
|
* Auditors are sorted by their canonicalized base URL.
|
||||||
|
*/
|
||||||
|
trusted_auditors: { [currency: string]: BackupTrustAuditor[] };
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Trusted exchange. Only applicable for local currencies (4-12 letter currency code).
|
||||||
|
*
|
||||||
|
* Exchanges are sorted by their canonicalized base URL.
|
||||||
|
*/
|
||||||
|
trusted_exchanges: { [currency: string]: BackupTrustExchange[] };
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Interning table for forgettable values of contract terms.
|
||||||
|
*
|
||||||
|
* Used to reduce storage space, as many forgettable items (product image,
|
||||||
|
* addresses, etc.) might be shared among many contract terms.
|
||||||
|
*/
|
||||||
|
intern_table: { [hash: string]: any };
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Trust declaration for an auditor.
|
||||||
|
*
|
||||||
|
* The trust applies based on the public key of
|
||||||
|
* the auditor, irrespective of what base URL the exchange
|
||||||
|
* is referencing.
|
||||||
|
*/
|
||||||
|
export interface BackupTrustAuditor {
|
||||||
|
/**
|
||||||
|
* Base URL of the auditor.
|
||||||
|
*/
|
||||||
|
auditor_base_url: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Public key of the auditor.
|
||||||
|
*/
|
||||||
|
auditor_pub: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Clock when the auditor trust has been added.
|
||||||
|
*
|
||||||
|
* Can be undefined if this entry represents a removal delta
|
||||||
|
* from the wallet's defaults.
|
||||||
|
*/
|
||||||
|
clock_added?: ClockValue;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Clock for when the auditor trust has been removed.
|
||||||
|
*/
|
||||||
|
clock_removed?: ClockValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Trust declaration for an exchange.
|
||||||
|
*
|
||||||
|
* The trust only applies for the combination of base URL
|
||||||
|
* and public key. If the master public key changes while the base
|
||||||
|
* URL stays the same, the exchange has to be re-added by a wallet update
|
||||||
|
* or by the user.
|
||||||
|
*/
|
||||||
|
export interface BackupTrustExchange {
|
||||||
|
/**
|
||||||
|
* Canonicalized exchange base URL.
|
||||||
|
*/
|
||||||
|
exchange_base_url: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Master public key of the exchange.
|
||||||
|
*/
|
||||||
|
exchange_master_pub: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Clock when the exchange trust has been added.
|
||||||
|
*
|
||||||
|
* Can be undefined if this entry represents a removal delta
|
||||||
|
* from the wallet's defaults.
|
||||||
|
*/
|
||||||
|
clock_added?: ClockValue;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Clock for when the exchange trust has been removed.
|
||||||
|
*/
|
||||||
|
clock_removed?: ClockValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -182,9 +293,9 @@ export class BackupBackupProvider {
|
|||||||
storage_limit_in_megabytes: number;
|
storage_limit_in_megabytes: number;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Last proposal ID to pay for the backup provider.
|
* Proposal IDs for payments to this provider.
|
||||||
*/
|
*/
|
||||||
pay_proposal_id?: string;
|
pay_proposal_ids: string[];
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -421,21 +532,6 @@ export enum BackupRefreshReason {
|
|||||||
Scheduled = "scheduled",
|
Scheduled = "scheduled",
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Planchet for a coin during refresh.
|
|
||||||
*/
|
|
||||||
export interface BackupRefreshPlanchet {
|
|
||||||
/**
|
|
||||||
* Private key for the coin.
|
|
||||||
*/
|
|
||||||
private_key: string;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Blinding key used.
|
|
||||||
*/
|
|
||||||
blinding_key: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Information about one refresh session, always part
|
* Information about one refresh session, always part
|
||||||
* of a refresh group.
|
* of a refresh group.
|
||||||
@ -443,45 +539,21 @@ export interface BackupRefreshPlanchet {
|
|||||||
* (Public key of the old coin is stored in the refresh group.)
|
* (Public key of the old coin is stored in the refresh group.)
|
||||||
*/
|
*/
|
||||||
export interface BackupRefreshSession {
|
export interface BackupRefreshSession {
|
||||||
/**
|
|
||||||
* Signature made by the old coin to confirm the melting.
|
|
||||||
*/
|
|
||||||
confirm_sig: string;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Hased denominations of the newly requested coins.
|
* Hased denominations of the newly requested coins.
|
||||||
*/
|
*/
|
||||||
new_denom_hashes: string[];
|
new_denom_hashes: string[];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Planchets for each cut-and-choose instance.
|
* Seed used to derive the planchets and
|
||||||
|
* transfer private keys for this refresh session.
|
||||||
*/
|
*/
|
||||||
planchets_for_gammas: BackupRefreshPlanchet[][];
|
session_secret_seed: string;
|
||||||
|
|
||||||
/**
|
|
||||||
* Private keys for the transfer public keys.
|
|
||||||
*/
|
|
||||||
transfer_privs: string[];
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The no-reveal-index after we've done the melting.
|
* The no-reveal-index after we've done the melting.
|
||||||
*/
|
*/
|
||||||
noreveal_index?: number;
|
noreveal_index?: number;
|
||||||
|
|
||||||
/**
|
|
||||||
* Hash of the session.
|
|
||||||
*/
|
|
||||||
hash: string;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Timestamp when the refresh session finished.
|
|
||||||
*/
|
|
||||||
timestamp_finished: Timestamp | undefined;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* When has this refresh session been created?
|
|
||||||
*/
|
|
||||||
timestamp_created: Timestamp;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -516,10 +588,10 @@ export interface BackupRefreshGroup {
|
|||||||
estimated_output_amount: BackupAmountString;
|
estimated_output_amount: BackupAmountString;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Coin is skipped (finished without a refresh session) because
|
* Did the refresh session finish (or was it unnecessary/impossible to create
|
||||||
* there is not enough value left on it.
|
* one)
|
||||||
*/
|
*/
|
||||||
skipped: boolean;
|
finished: boolean;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Refresh session (if created) or undefined it not created yet.
|
* Refresh session (if created) or undefined it not created yet.
|
||||||
@ -620,7 +692,7 @@ export interface BackupRefundItemCommon {
|
|||||||
*
|
*
|
||||||
* Might be lower in practice when two refunds on the same
|
* Might be lower in practice when two refunds on the same
|
||||||
* coin are refreshed in the same refresh operation.
|
* coin are refreshed in the same refresh operation.
|
||||||
*
|
*
|
||||||
* Used to display fees, and stored since it's expensive to recompute
|
* Used to display fees, and stored since it's expensive to recompute
|
||||||
* accurately.
|
* accurately.
|
||||||
*/
|
*/
|
||||||
@ -891,7 +963,7 @@ export interface BackupReserve {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Wire fee for one wire method as stored in the
|
* Wire fee for one wire payment target type as stored in the
|
||||||
* wallet's database.
|
* wallet's database.
|
||||||
*
|
*
|
||||||
* (Flattened to a list to make the declaration simpler).
|
* (Flattened to a list to make the declaration simpler).
|
||||||
@ -1023,10 +1095,7 @@ export interface BackupExchange {
|
|||||||
*/
|
*/
|
||||||
accounts: {
|
accounts: {
|
||||||
payto_uri: string;
|
payto_uri: string;
|
||||||
/**
|
master_sig: string;
|
||||||
* Optional, since older wallets don't store this.
|
|
||||||
*/
|
|
||||||
master_sig?: string;
|
|
||||||
}[];
|
}[];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -507,6 +507,7 @@ export enum ExchangeUpdateStatus {
|
|||||||
|
|
||||||
export interface ExchangeBankAccount {
|
export interface ExchangeBankAccount {
|
||||||
payto_uri: string;
|
payto_uri: string;
|
||||||
|
master_sig: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface ExchangeWireInfo {
|
export interface ExchangeWireInfo {
|
||||||
|
Loading…
Reference in New Issue
Block a user