gnunet-svn
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[taler-wallet-core] branch master updated: wallet-core,wallet-cli: prope


From: gnunet
Subject: [taler-wallet-core] branch master updated: wallet-core,wallet-cli: properly serialize manual DB export
Date: Wed, 30 Aug 2023 15:54:46 +0200

This is an automated email from the git hooks/post-receive script.

dold pushed a commit to branch master
in repository wallet-core.

The following commit(s) were added to refs/heads/master by this push:
     new 88f7338d7 wallet-core,wallet-cli: properly serialize manual DB export
88f7338d7 is described below

commit 88f7338d7c84ac2a774b483ccff25faf6ceeb879
Author: Florian Dold <florian@dold.me>
AuthorDate: Wed Aug 30 15:54:44 2023 +0200

    wallet-core,wallet-cli: properly serialize manual DB export
---
 packages/taler-wallet-cli/src/index.ts |  99 +++---------------------
 packages/taler-wallet-core/src/db.ts   | 135 ++++++++++++++++++++++++++-------
 2 files changed, 115 insertions(+), 119 deletions(-)

diff --git a/packages/taler-wallet-cli/src/index.ts 
b/packages/taler-wallet-cli/src/index.ts
index 9d840e5bb..d7966a9ca 100644
--- a/packages/taler-wallet-cli/src/index.ts
+++ b/packages/taler-wallet-cli/src/index.ts
@@ -257,8 +257,7 @@ async function createLocalWallet(
     },
     cryptoWorkerType: walletCliArgs.wallet.cryptoWorker as any,
     config: {
-      features: {
-      },
+      features: {},
       testing: {
         devModeActive: checkEnvFlag("TALER_WALLET_DEV_MODE"),
         denomselAllowLate: checkEnvFlag(
@@ -651,9 +650,12 @@ walletCli
           });
           break;
         case TalerUriAction.Reward: {
-          const res = await 
wallet.client.call(WalletApiOperation.PrepareReward, {
-            talerRewardUri: uri,
-          });
+          const res = await wallet.client.call(
+            WalletApiOperation.PrepareReward,
+            {
+              talerRewardUri: uri,
+            },
+          );
           console.log("tip status", res);
           await wallet.client.call(WalletApiOperation.AcceptReward, {
             walletRewardId: res.walletRewardId,
@@ -874,96 +876,13 @@ const backupCli = walletCli.subcommand("backupArgs", 
"backup", {
   help: "Subcommands for backups",
 });
 
-backupCli
-  .subcommand("setDeviceId", "set-device-id")
-  .requiredArgument("deviceId", clk.STRING, {
-    help: "new device ID",
-  })
-  .action(async (args) => {
-    await withWallet(args, async (wallet) => {
-      await wallet.client.call(WalletApiOperation.SetWalletDeviceId, {
-        walletDeviceId: args.setDeviceId.deviceId,
-      });
-    });
-  });
-
-backupCli.subcommand("exportPlain", "export-plain").action(async (args) => {
+backupCli.subcommand("exportDb", "export-db").action(async (args) => {
   await withWallet(args, async (wallet) => {
-    const backup = await wallet.client.call(
-      WalletApiOperation.ExportBackupPlain,
-      {},
-    );
+    const backup = await wallet.client.call(WalletApiOperation.ExportDb, {});
     console.log(JSON.stringify(backup, undefined, 2));
   });
 });
 
-backupCli.subcommand("recoverySave", "save-recovery").action(async (args) => {
-  await withWallet(args, async (wallet) => {
-    const recoveryJson = await wallet.client.call(
-      WalletApiOperation.ExportBackupRecovery,
-      {},
-    );
-    console.log(JSON.stringify(recoveryJson, undefined, 2));
-  });
-});
-
-backupCli.subcommand("run", "run").action(async (args) => {
-  await withWallet(args, async (wallet) => {
-    await wallet.client.call(WalletApiOperation.RunBackupCycle, {});
-  });
-});
-
-backupCli.subcommand("status", "status").action(async (args) => {
-  await withWallet(args, async (wallet) => {
-    const status = await wallet.client.call(
-      WalletApiOperation.GetBackupInfo,
-      {},
-    );
-    console.log(JSON.stringify(status, undefined, 2));
-  });
-});
-
-backupCli
-  .subcommand("recoveryLoad", "load-recovery")
-  .maybeOption("strategy", ["--strategy"], clk.STRING, {
-    help: "Strategy for resolving a conflict with the existing wallet key 
('theirs' or 'ours')",
-  })
-  .action(async (args) => {
-    await withWallet(args, async (wallet) => {
-      const data = JSON.parse(await read(process.stdin));
-      let strategy: RecoveryMergeStrategy | undefined;
-      const stratStr = args.recoveryLoad.strategy;
-      if (stratStr) {
-        if (stratStr === "theirs") {
-          strategy = RecoveryMergeStrategy.Theirs;
-        } else if (stratStr === "ours") {
-          strategy = RecoveryMergeStrategy.Theirs;
-        } else {
-          throw Error("invalid recovery strategy");
-        }
-      }
-      await wallet.client.call(WalletApiOperation.ImportBackupRecovery, {
-        recovery: data,
-        strategy,
-      });
-    });
-  });
-
-backupCli
-  .subcommand("addProvider", "add-provider")
-  .requiredArgument("url", clk.STRING)
-  .maybeArgument("name", clk.STRING)
-  .flag("activate", ["--activate"])
-  .action(async (args) => {
-    await withWallet(args, async (wallet) => {
-      await wallet.client.call(WalletApiOperation.AddBackupProvider, {
-        backupProviderBaseUrl: args.addProvider.url,
-        activate: args.addProvider.activate,
-        name: args.addProvider.name || args.addProvider.url,
-      });
-    });
-  });
-
 const depositCli = walletCli.subcommand("depositArgs", "deposit", {
   help: "Subcommands for depositing money to payto:// accounts",
 });
diff --git a/packages/taler-wallet-core/src/db.ts 
b/packages/taler-wallet-core/src/db.ts
index c550ab675..2dbf5dade 100644
--- a/packages/taler-wallet-core/src/db.ts
+++ b/packages/taler-wallet-core/src/db.ts
@@ -23,6 +23,7 @@ import {
   IDBFactory,
   IDBObjectStore,
   IDBTransaction,
+  structuredEncapsulate,
 } from "@gnu-taler/idb-bridge";
 import {
   AgeCommitmentProof,
@@ -566,10 +567,31 @@ export interface ExchangeDetailsPointer {
   updateClock: TalerPreciseTimestamp;
 }
 
+export enum ExchangeEntryDbRecordStatus {
+  Preset = 1,
+  Ephemeral = 2,
+  Used = 3,
+}
+
+export enum ExchangeEntryDbUpdateStatus {
+  Initial = 1,
+  InitialUpdate = 2,
+  Suspended = 3,
+  Failed = 4,
+  OutdatedUpdate = 5,
+  Ready = 6,
+  ReadyUpdate = 7,
+}
+
+/**
+ * Timestamp stored as a IEEE 754 double, in milliseconds.
+ */
+export type DbIndexableTimestampMs = number;
+
 /**
  * Exchange record as stored in the wallet's database.
  */
-export interface ExchangeRecord {
+export interface ExchangeEntryRecord {
   /**
    * Base url of the exchange.
    */
@@ -594,13 +616,12 @@ export interface ExchangeRecord {
    */
   detailsPointer: ExchangeDetailsPointer | undefined;
 
-  /**
-   * Is this a permanent or temporary exchange record?
-   */
-  permanent: boolean;
+  entryStatus: ExchangeEntryDbRecordStatus;
+
+  updateStatus: ExchangeEntryDbUpdateStatus;
 
   /**
-   * Last time when the exchange was updated (both /keys and /wire).
+   * Last time when the exchange /keys info was updated.
    */
   lastUpdate: TalerPreciseTimestamp | undefined;
 
@@ -608,20 +629,21 @@ export interface ExchangeRecord {
    * Next scheduled update for the exchange.
    *
    * (This field must always be present, so we can index on the timestamp.)
+   *
+   * FIXME: To index on the timestamp, this needs to be a number of
+   * binary timestamp!
    */
-  nextUpdate: TalerPreciseTimestamp;
+  nextUpdateStampMs: DbIndexableTimestampMs;
 
   lastKeysEtag: string | undefined;
 
-  lastWireEtag: string | undefined;
-
   /**
    * Next time that we should check if coins need to be refreshed.
    *
    * Updated whenever the exchange's denominations are updated or when
    * the refresh check has been done.
    */
-  nextRefreshCheck: TalerPreciseTimestamp;
+  nextRefreshCheckStampMs: DbIndexableTimestampMs;
 
   /**
    * Public key of the reserve that we're currently using for
@@ -2424,7 +2446,7 @@ export const WalletStoresV1 = {
   ),
   exchanges: describeStore(
     "exchanges",
-    describeContents<ExchangeRecord>({
+    describeContents<ExchangeEntryRecord>({
       keyPath: "baseUrl",
     }),
     {},
@@ -2713,11 +2735,10 @@ export type WalletDbReadOnlyTransaction<
   Stores extends StoreNames<typeof WalletStoresV1> & string,
 > = DbReadOnlyTransaction<typeof WalletStoresV1, Stores>;
 
-export type WalletReadWriteTransaction<
+export type WalletDbReadWriteTransaction<
   Stores extends StoreNames<typeof WalletStoresV1> & string,
 > = DbReadWriteTransaction<typeof WalletStoresV1, Stores>;
 
-
 /**
  * An applied migration.
  */
@@ -2748,32 +2769,88 @@ export const walletMetadataStore = {
   ),
 };
 
-export function exportDb(db: IDBDatabase): Promise<any> {
-  const dump = {
-    name: db.name,
-    stores: {} as { [s: string]: any },
+export interface DbDumpRecord {
+  /**
+   * Key, serialized with structuredEncapsulated.
+   */
+  key: any;
+  /**
+   * Value, serialized with structuredEncapsulated.
+   */
+  value: any;
+}
+
+export interface DbIndexDump {
+  keyPath: string | string[];
+  multiEntry: boolean;
+  unique: boolean;
+}
+
+export interface DbStoreDump {
+  keyPath?: string | string[];
+  autoIncrement: boolean;
+  indexes: { [indexName: string]: DbIndexDump };
+  records: DbDumpRecord[];
+}
+
+export interface DbDumpDatabase {
+  version: number;
+  stores: { [storeName: string]: DbStoreDump };
+}
+
+export interface DbDump {
+  databases: {
+    [name: string]: DbDumpDatabase;
+  };
+}
+
+export function exportDb(db: IDBDatabase): Promise<DbDump> {
+  const dbDump: DbDump = {
+    databases: {},
+  };
+
+  const walletDb: DbDumpDatabase = {
     version: db.version,
+    stores: {},
   };
+  dbDump.databases[db.name] = walletDb;
 
   return new Promise((resolve, reject) => {
     const tx = db.transaction(Array.from(db.objectStoreNames));
     tx.addEventListener("complete", () => {
-      resolve(dump);
+      resolve(dbDump);
     });
     // tslint:disable-next-line:prefer-for-of
     for (let i = 0; i < db.objectStoreNames.length; i++) {
       const name = db.objectStoreNames[i];
-      const storeDump = {} as { [s: string]: any };
-      dump.stores[name] = storeDump;
-      tx.objectStore(name)
-        .openCursor()
-        .addEventListener("success", (e: Event) => {
-          const cursor = (e.target as any).result;
-          if (cursor) {
-            storeDump[cursor.key] = cursor.value;
-            cursor.continue();
-          }
-        });
+      const store = tx.objectStore(name);
+      const storeDump: DbStoreDump = {
+        autoIncrement: store.autoIncrement,
+        keyPath: store.keyPath,
+        indexes: {},
+        records: [],
+      };
+      const indexNames = store.indexNames;
+      for (let j = 0; j < indexNames.length; j++) {
+        const idxName = indexNames[j];
+        const index = store.index(idxName);
+        storeDump.indexes[idxName] = {
+          keyPath: index.keyPath,
+          multiEntry: index.multiEntry,
+          unique: index.unique,
+        };
+      }
+      walletDb.stores[name] = storeDump;
+      store.openCursor().addEventListener("success", (e: Event) => {
+        const cursor = (e.target as any).result;
+        if (cursor) {
+          storeDump.records.push({
+            key: structuredEncapsulate(cursor.key),
+            value: structuredEncapsulate(cursor.value),
+          });
+          cursor.continue();
+        }
+      });
     }
   });
 }

-- 
To stop receiving notification emails like this one, please contact
gnunet@gnunet.org.



reply via email to

[Prev in Thread] Current Thread [Next in Thread]