gnunet-svn
[Top][All Lists]
Advanced

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

[taler-wallet-core] branch master updated (4c614429 -> 857a2b9d)


From: gnunet
Subject: [taler-wallet-core] branch master updated (4c614429 -> 857a2b9d)
Date: Mon, 11 May 2020 18:17:43 +0200

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

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

    from 4c614429 also create key material for planchets in smaller bites
     new d7ee7866 create planchets only in one place
     new 277a513a directly withdraw after creating planchet
     new 857a2b9d perf: reserve history in separate object store

The 3 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.


Summary of changes:
 src/db.ts                  |   2 +-
 src/operations/balance.ts  |   6 ++-
 src/operations/history.ts  |   7 +++-
 src/operations/reserves.ts | 101 +++++++++++++++++++++++----------------------
 src/operations/withdraw.ts |  16 ++++---
 src/types/dbTypes.ts       |  14 ++++++-
 src/webex/pages/popup.tsx  |   7 ++++
 7 files changed, 93 insertions(+), 60 deletions(-)

diff --git a/src/db.ts b/src/db.ts
index efc3b78a..098767b5 100644
--- a/src/db.ts
+++ b/src/db.ts
@@ -7,7 +7,7 @@ import { openDatabase, Database, Store, Index } from 
"./util/query";
  * with each major change.  When incrementing the major version,
  * the wallet should import data from the previous version.
  */
-const TALER_DB_NAME = "taler-walletdb-v2";
+const TALER_DB_NAME = "taler-walletdb-v3";
 
 /**
  * Current database minor version, should be incremented
diff --git a/src/operations/balance.ts b/src/operations/balance.ts
index b5c1ec79..6f913502 100644
--- a/src/operations/balance.ts
+++ b/src/operations/balance.ts
@@ -145,7 +145,7 @@ export async function getBalances(
 ): Promise<WalletBalance> {
   logger.trace("starting to compute balance");
 
-  return await ws.db.runWithReadTransaction(
+  const wbal = await ws.db.runWithReadTransaction(
     [
       Stores.coins,
       Stores.refreshGroups,
@@ -157,4 +157,8 @@ export async function getBalances(
       return getBalancesInsideTransaction(ws, tx);
     },
   );
+
+  logger.trace("finished computing wallet balance");
+
+  return wbal;
 }
diff --git a/src/operations/history.ts b/src/operations/history.ts
index 669a6cf8..1271c56e 100644
--- a/src/operations/history.ts
+++ b/src/operations/history.ts
@@ -172,6 +172,7 @@ export async function getHistory(
       Stores.purchases,
       Stores.refreshGroups,
       Stores.reserves,
+      Stores.reserveHistory,
       Stores.tips,
       Stores.withdrawalGroups,
       Stores.payEvents,
@@ -384,8 +385,12 @@ export async function getHistory(
             type: ReserveType.Manual,
           };
         }
+        const hist = await tx.get(Stores.reserveHistory, reserve.reservePub);
+        if (!hist) {
+          throw Error("inconsistent database");
+        }
         const s = summarizeReserveHistory(
-          reserve.reserveTransactions,
+          hist.reserveTransactions,
           reserve.currency,
         );
         history.push({
diff --git a/src/operations/reserves.ts b/src/operations/reserves.ts
index 786f4f51..2bbb085d 100644
--- a/src/operations/reserves.ts
+++ b/src/operations/reserves.ts
@@ -33,8 +33,8 @@ import {
   updateRetryInfoTimeout,
   ReserveUpdatedEventRecord,
   WalletReserveHistoryItemType,
-  PlanchetRecord,
   WithdrawalSourceType,
+  ReserveHistoryRecord,
 } from "../types/dbTypes";
 import { Logger } from "../util/logging";
 import { Amounts } from "../util/amounts";
@@ -114,11 +114,15 @@ export async function createReserve(
     lastSuccessfulStatusQuery: undefined,
     retryInfo: initRetryInfo(),
     lastError: undefined,
-    reserveTransactions: [],
     currency: req.amount.currency,
   };
 
-  reserveRecord.reserveTransactions.push({
+  const reserveHistoryRecord: ReserveHistoryRecord = {
+    reservePub: keypair.pub,
+    reserveTransactions: [],
+  };
+
+  reserveHistoryRecord.reserveTransactions.push({
     type: WalletReserveHistoryItemType.Credit,
     expectedAmount: req.amount,
   });
@@ -161,7 +165,12 @@ export async function createReserve(
   const cr: CurrencyRecord = currencyRecord;
 
   const resp = await ws.db.runWithWriteTransaction(
-    [Stores.currencies, Stores.reserves, Stores.bankWithdrawUris],
+    [
+      Stores.currencies,
+      Stores.reserves,
+      Stores.reserveHistory,
+      Stores.bankWithdrawUris,
+    ],
     async (tx) => {
       // Check if we have already created a reserve for that 
bankWithdrawStatusUrl
       if (reserveRecord.bankWithdrawStatusUrl) {
@@ -188,6 +197,7 @@ export async function createReserve(
       }
       await tx.put(Stores.currencies, cr);
       await tx.put(Stores.reserves, reserveRecord);
+      await tx.put(Stores.reserveHistory, reserveHistoryRecord);
       const r: CreateReserveResponse = {
         exchange: canonExchange,
         reservePub: keypair.pub,
@@ -462,7 +472,7 @@ async function updateReserve(
   const balance = Amounts.parseOrThrow(reserveInfo.balance);
   const currency = balance.currency;
   await ws.db.runWithWriteTransaction(
-    [Stores.reserves, Stores.reserveUpdatedEvents],
+    [Stores.reserves, Stores.reserveUpdatedEvents, Stores.reserveHistory],
     async (tx) => {
       const r = await tx.get(Stores.reserves, reservePub);
       if (!r) {
@@ -472,14 +482,19 @@ async function updateReserve(
         return;
       }
 
+      const hist = await tx.get(Stores.reserveHistory, reservePub);
+      if (!hist) {
+        throw Error("inconsistent database");
+      }
+
       const newHistoryTransactions = reserveInfo.history.slice(
-        r.reserveTransactions.length,
+        hist.reserveTransactions.length,
       );
 
       const reserveUpdateId = encodeCrock(getRandomBytes(32));
 
       const reconciled = reconcileReserveHistory(
-        r.reserveTransactions,
+        hist.reserveTransactions,
         reserveInfo.history,
       );
 
@@ -514,9 +529,10 @@ async function updateReserve(
         r.retryInfo = initRetryInfo(false);
       }
       r.lastSuccessfulStatusQuery = getTimestampNow();
-      r.reserveTransactions = reconciled.updatedLocalHistory;
+      hist.reserveTransactions = reconciled.updatedLocalHistory;
       r.lastError = undefined;
       await tx.put(Stores.reserves, r);
+      await tx.put(Stores.reserveHistory, hist);
     },
   );
   ws.notify({ type: NotificationType.ReserveUpdated });
@@ -602,17 +618,29 @@ async function depleteReserve(
   ws: InternalWalletState,
   reservePub: string,
 ): Promise<void> {
-  const reserve = await ws.db.get(Stores.reserves, reservePub);
+  let reserve: ReserveRecord | undefined;
+  let hist: ReserveHistoryRecord | undefined;
+  await ws.db.runWithReadTransaction(
+    [Stores.reserves, Stores.reserveHistory],
+    async (tx) => {
+      reserve = await tx.get(Stores.reserves, reservePub);
+      hist = await tx.get(Stores.reserveHistory, reservePub);
+    },
+  );
+
   if (!reserve) {
     return;
   }
+  if (!hist) {
+    throw Error("inconsistent database");
+  }
   if (reserve.reserveStatus !== ReserveRecordStatus.WITHDRAWING) {
     return;
   }
   logger.trace(`depleting reserve ${reservePub}`);
 
   const summary = summarizeReserveHistory(
-    reserve.reserveTransactions,
+    hist.reserveTransactions,
     reserve.currency,
   );
 
@@ -647,40 +675,6 @@ async function depleteReserve(
 
   const withdrawalGroupId = encodeCrock(randomBytes(32));
 
-  const planchets: PlanchetRecord[] = [];
-  let coinIdx = 0;
-  for (let i = 0; i < denomsForWithdraw.selectedDenoms.length; i++) {
-    const d = denomsForWithdraw.selectedDenoms[i];
-    const denom = d.denom;
-    for (let j = 0; j < d.count; j++) {
-      const r = await ws.cryptoApi.createPlanchet({
-        denomPub: denom.denomPub,
-        feeWithdraw: denom.feeWithdraw,
-        reservePriv: reserve.reservePriv,
-        reservePub: reserve.reservePub,
-        value: denom.value,
-      });
-      const planchet: PlanchetRecord = {
-        blindingKey: r.blindingKey,
-        coinEv: r.coinEv,
-        coinEvHash: r.coinEvHash,
-        coinIdx,
-        coinPriv: r.coinPriv,
-        coinPub: r.coinPub,
-        coinValue: r.coinValue,
-        denomPub: r.denomPub,
-        denomPubHash: r.denomPubHash,
-        isFromTip: false,
-        reservePub: r.reservePub,
-        withdrawalDone: false,
-        withdrawSig: r.withdrawSig,
-        withdrawalGroupId: withdrawalGroupId,
-      };
-      planchets.push(planchet);
-      coinIdx++;
-    }
-  }
-
   logger.trace("created plachets");
 
   const withdrawalRecord: WithdrawalGroupRecord = {
@@ -708,7 +702,12 @@ async function depleteReserve(
   };
 
   const success = await ws.db.runWithWriteTransaction(
-    [Stores.withdrawalGroups, Stores.reserves, Stores.planchets],
+    [
+      Stores.withdrawalGroups,
+      Stores.reserves,
+      Stores.reserveHistory,
+      Stores.planchets,
+    ],
     async (tx) => {
       const newReserve = await tx.get(Stores.reserves, reservePub);
       if (!newReserve) {
@@ -717,8 +716,12 @@ async function depleteReserve(
       if (newReserve.reserveStatus !== ReserveRecordStatus.WITHDRAWING) {
         return false;
       }
+      const newHist = await tx.get(Stores.reserveHistory, reservePub);
+      if (!newHist) {
+        throw Error("inconsistent database");
+      }
       const newSummary = summarizeReserveHistory(
-        newReserve.reserveTransactions,
+        newHist.reserveTransactions,
         newReserve.currency,
       );
       if (
@@ -737,7 +740,7 @@ async function depleteReserve(
         const sd = denomsForWithdraw.selectedDenoms[i];
         for (let j = 0; j < sd.count; j++) {
           const amt = Amounts.add(sd.denom.value, sd.denom.feeWithdraw).amount;
-          newReserve.reserveTransactions.push({
+          newHist.reserveTransactions.push({
             type: WalletReserveHistoryItemType.Withdraw,
             expectedAmount: amt,
           });
@@ -746,10 +749,8 @@ async function depleteReserve(
       newReserve.reserveStatus = ReserveRecordStatus.DORMANT;
       newReserve.retryInfo = initRetryInfo(false);
       await tx.put(Stores.reserves, newReserve);
+      await tx.put(Stores.reserveHistory, newHist);
       await tx.put(Stores.withdrawalGroups, withdrawalRecord);
-      for (const p of planchets) {
-        await tx.put(Stores.planchets, p);
-      }
       return true;
     },
   );
diff --git a/src/operations/withdraw.ts b/src/operations/withdraw.ts
index b89dac77..e1c4ed57 100644
--- a/src/operations/withdraw.ts
+++ b/src/operations/withdraw.ts
@@ -189,7 +189,7 @@ async function processPlanchet(
   if (!withdrawalGroup) {
     return;
   }
-  const planchet = await ws.db.getIndexed(Stores.planchets.byGroupAndIndex, [
+  let planchet = await ws.db.getIndexed(Stores.planchets.byGroupAndIndex, [
     withdrawalGroupId,
     coinIdx,
   ]);
@@ -247,12 +247,15 @@ async function processPlanchet(
         coinIdx,
       ]);
       if (p) {
+        planchet = p;
         return;
       }
       await tx.put(Stores.planchets, newPlanchet);
+      planchet = newPlanchet;
     });
-    console.log("processPlanchet: planchet not found");
-    return;
+  }
+  if (!planchet) {
+    throw Error("invariant violated");
   }
   if (planchet.withdrawalDone) {
     console.log("processPlanchet: planchet already withdrawn");
@@ -332,6 +335,8 @@ async function processPlanchet(
 
   let withdrawalGroupFinished = false;
 
+  const planchetCoinPub = planchet.coinPub;
+
   const success = await ws.db.runWithWriteTransaction(
     [Stores.coins, Stores.withdrawalGroups, Stores.reserves, Stores.planchets],
     async (tx) => {
@@ -339,7 +344,7 @@ async function processPlanchet(
       if (!ws) {
         return false;
       }
-      const p = await tx.get(Stores.planchets, planchet.coinPub);
+      const p = await tx.get(Stores.planchets, planchetCoinPub);
       if (!p) {
         return false;
       }
@@ -522,6 +527,7 @@ async function processInBatches(workGen: 
Iterator<Promise<void>>, batchSize: num
     if (batch.length == 0) {
       break;
     }
+    logger.trace(`processing withdrawal batch of ${batch.length} elements`);
     await Promise.all(batch);
   }
 }
@@ -558,7 +564,7 @@ async function processWithdrawGroupImpl(
 
   // Withdraw coins in batches.
   // The batch size is relatively large
-  await processInBatches(genWork(), 50);
+  await processInBatches(genWork(), 10);
 }
 
 export async function getExchangeWithdrawalInfo(
diff --git a/src/types/dbTypes.ts b/src/types/dbTypes.ts
index 26fcca9e..4cf19a56 100644
--- a/src/types/dbTypes.ts
+++ b/src/types/dbTypes.ts
@@ -210,6 +210,11 @@ export type WalletReserveHistoryItem =
   | WalletReserveHistoryRecoupItem
   | WalletReserveHistoryClosingItem;
 
+export interface ReserveHistoryRecord {
+  reservePub: string;
+  reserveTransactions: WalletReserveHistoryItem[];
+}
+
 /**
  * A reserve record as stored in the wallet's database.
  */
@@ -295,8 +300,6 @@ export interface ReserveRecord {
    * (either talking to the bank or the exchange).
    */
   lastError: OperationError | undefined;
-
-  reserveTransactions: WalletReserveHistoryItem[];
 }
 
 /**
@@ -1639,6 +1642,12 @@ export namespace Stores {
     }
   }
 
+  class ReserveHistoryStore extends Store<ReserveHistoryRecord> {
+    constructor() {
+      super("reserveHistory", { keyPath: "reservePub" });
+    }
+  }
+
   class TipsStore extends Store<TipRecord> {
     constructor() {
       super("tips", { keyPath: "tipId" });
@@ -1725,6 +1734,7 @@ export namespace Stores {
     keyPath: "recoupGroupId",
   });
   export const reserves = new ReservesStore();
+  export const reserveHistory = new ReserveHistoryStore();
   export const purchases = new PurchasesStore();
   export const tips = new TipsStore();
   export const senderWires = new SenderWiresStore();
diff --git a/src/webex/pages/popup.tsx b/src/webex/pages/popup.tsx
index 450aae4c..4d3c65b2 100644
--- a/src/webex/pages/popup.tsx
+++ b/src/webex/pages/popup.tsx
@@ -177,6 +177,7 @@ class WalletBalanceView extends React.Component<any, any> {
   private gotError = false;
   private canceler: (() => void) | undefined = undefined;
   private unmount = false;
+  private updateBalanceRunning = false;
 
   componentWillMount(): void {
     this.canceler = wxApi.onUpdateNotification(() => this.updateBalance());
@@ -192,6 +193,10 @@ class WalletBalanceView extends React.Component<any, any> {
   }
 
   async updateBalance(): Promise<void> {
+    if (this.updateBalanceRunning) {
+      return;
+    }
+    this.updateBalanceRunning = true;
     let balance: WalletBalance;
     try {
       balance = await wxApi.getBalance();
@@ -203,6 +208,8 @@ class WalletBalanceView extends React.Component<any, any> {
       console.error("could not retrieve balances", e);
       this.setState({});
       return;
+    } finally {
+      this.updateBalanceRunning = false;
     }
     if (this.unmount) {
       return;

-- 
To stop receiving notification emails like this one, please contact
address@hidden.



reply via email to

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