gnunet-svn
[Top][All Lists]
Advanced

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

[taler-wallet-core] 02/02: wallet-core: remove coinAllocationId, simplif


From: gnunet
Subject: [taler-wallet-core] 02/02: wallet-core: remove coinAllocationId, simplify coin history store
Date: Thu, 13 Jun 2024 19:55:53 +0200

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

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

commit 331ff2a22ddbe7512e3a54235a986e7275b88920
Author: Florian Dold <florian@dold.me>
AuthorDate: Thu Jun 13 19:55:48 2024 +0200

    wallet-core: remove coinAllocationId, simplify coin history store
---
 packages/taler-util/src/wallet-types.ts            |  6 ---
 packages/taler-wallet-core/src/common.ts           | 32 +++---------
 packages/taler-wallet-core/src/db.ts               | 58 +++++++++++-----------
 packages/taler-wallet-core/src/deposits.ts         | 13 ++++-
 packages/taler-wallet-core/src/pay-merchant.ts     | 20 ++------
 .../taler-wallet-core/src/pay-peer-pull-debit.ts   | 19 ++-----
 .../taler-wallet-core/src/pay-peer-push-debit.ts   | 10 +---
 packages/taler-wallet-core/src/recoup.ts           | 30 +++++------
 packages/taler-wallet-core/src/refresh.ts          | 11 ----
 packages/taler-wallet-core/src/wallet.ts           |  6 ---
 packages/taler-wallet-core/src/withdraw.ts         |  1 -
 11 files changed, 73 insertions(+), 133 deletions(-)

diff --git a/packages/taler-util/src/wallet-types.ts 
b/packages/taler-util/src/wallet-types.ts
index 8fa5b1e69..82ccb4fc4 100644
--- a/packages/taler-util/src/wallet-types.ts
+++ b/packages/taler-util/src/wallet-types.ts
@@ -664,12 +664,6 @@ export interface CoinDumpJson {
      */
     withdrawal_reserve_pub: string | undefined;
     coin_status: CoinStatus;
-    spend_allocation:
-      | {
-          id: string;
-          amount: AmountString;
-        }
-      | undefined;
     /**
      * Information about the age restriction
      */
diff --git a/packages/taler-wallet-core/src/common.ts 
b/packages/taler-wallet-core/src/common.ts
index 13c875575..9f63c74d5 100644
--- a/packages/taler-wallet-core/src/common.ts
+++ b/packages/taler-wallet-core/src/common.ts
@@ -74,9 +74,9 @@ export interface CoinsSpendInfo {
   contributions: AmountJson[];
   refreshReason: RefreshReason;
   /**
-   * Identifier for what the coin has been spent for.
+   * Transaction for which the coin is spent.
    */
-  allocationId: TransactionIdStr;
+  transactionId: TransactionIdStr;
 }
 
 export async function makeCoinsVisible(
@@ -149,11 +149,16 @@ export async function makeCoinAvailable(
   await tx.coinAvailability.put(car);
 }
 
+/**
+ * Spend coins. Marks the coins as used, adds a coin history items
+ * and creates refresh group.
+ */
 export async function spendCoins(
   wex: WalletExecutionContext,
   tx: WalletDbReadWriteTransaction<
     [
       "coins",
+      "coinHistory",
       "coinAvailability",
       "refreshGroups",
       "refreshSessions",
@@ -194,28 +199,7 @@ export async function spendCoins(
       `age denom info is missing for ${coin.maxAge}`,
     );
     const contrib = csi.contributions[i];
-    if (coin.status !== CoinStatus.Fresh) {
-      const alloc = coin.spendAllocation;
-      if (!alloc) {
-        continue;
-      }
-      if (alloc.id !== csi.allocationId) {
-        // FIXME: assign error code
-        logger.info("conflicting coin allocation ID");
-        logger.info(`old ID: ${alloc.id}, new ID: ${csi.allocationId}`);
-        throw Error("conflicting coin allocation (id)");
-      }
-      if (0 !== Amounts.cmp(alloc.amount, contrib)) {
-        // FIXME: assign error code
-        throw Error("conflicting coin allocation (contrib)");
-      }
-      continue;
-    }
     coin.status = CoinStatus.Dormant;
-    coin.spendAllocation = {
-      id: csi.allocationId,
-      amount: Amounts.stringify(contrib),
-    };
     const remaining = Amounts.sub(denom.value, contrib);
     if (remaining.saturated) {
       throw Error("not enough remaining balance on coin for payment");
@@ -247,7 +231,7 @@ export async function spendCoins(
     Amounts.currencyOf(csi.contributions[0]),
     refreshCoinPubs,
     csi.refreshReason,
-    csi.allocationId,
+    csi.transactionId,
   );
 }
 
diff --git a/packages/taler-wallet-core/src/db.ts 
b/packages/taler-wallet-core/src/db.ts
index 0ce838fd2..bf5d29603 100644
--- a/packages/taler-wallet-core/src/db.ts
+++ b/packages/taler-wallet-core/src/db.ts
@@ -151,7 +151,7 @@ export const CURRENT_DB_CONFIG_KEY = "currentMainDbName";
  * backwards-compatible way or object stores and indices
  * are added.
  */
-export const WALLET_DB_MINOR_VERSION = 10;
+export const WALLET_DB_MINOR_VERSION = 11;
 
 declare const symDbProtocolTimestamp: unique symbol;
 
@@ -893,15 +893,6 @@ export interface CoinRecord {
    */
   visible?: number;
 
-  /**
-   * Information about what the coin has been allocated for.
-   *
-   * Used for:
-   * - Diagnostics
-   * - Idempotency of applying a coin selection (e.g. after re-selection)
-   */
-  spendAllocation: CoinAllocation | undefined;
-
   /**
    * Maximum age of purchases that can be made with this coin.
    *
@@ -912,36 +903,44 @@ export interface CoinRecord {
   ageCommitmentProof: AgeCommitmentProof | undefined;
 }
 
-export type HistoryItem =
+export type WalletCoinHistoryItem =
   | {
       type: "withdraw";
       transactionId: TransactionIdStr;
     }
-  | { type: "spend"; transactionId: TransactionIdStr; amount: AmountString }
-  | { type: "refresh"; transactionId: TransactionIdStr; amount: AmountString }
-  | { type: "recoup"; transactionId: TransactionIdStr; amount: AmountString }
-  | { type: "refund"; transactionId: TransactionIdStr; amount: AmountString };
+  | {
+      type: "spend";
+      transactionId: TransactionIdStr;
+      amount: AmountString;
+    }
+  | {
+      type: "refresh";
+      transactionId: TransactionIdStr;
+      amount: AmountString;
+    }
+  | {
+      type: "recoup";
+      transactionId: TransactionIdStr;
+      amount: AmountString;
+    }
+  | {
+      type: "refund";
+      transactionId: TransactionIdStr;
+      amount: AmountString;
+    };
 
 /**
  * History event for a coin from the wallet's perspective.
  */
 export interface CoinHistoryRecord {
   coinPub: string;
-
-  timestamp: DbPreciseTimestamp;
-
-  item: HistoryItem;
-}
-
-/**
- * Coin allocation, i.e. what a coin has been used for.
- */
-export interface CoinAllocation {
   /**
-   * ID of the allocation, should be the ID of the transaction that
+   * History items for the coin.
+   *
+   * We store this as an array in the object store, as the coin history
+   * is pretty much always very small.
    */
-  id: TransactionIdStr;
-  amount: AmountString;
+  history: WalletCoinHistoryItem[];
 }
 
 export enum RefreshCoinStatus {
@@ -2447,7 +2446,8 @@ export const WalletStoresV1 = {
   coinHistory: describeStoreV2({
     storeName: "coinHistory",
     recordCodec: passthroughCodec<CoinHistoryRecord>(),
-    keyPath: ["coinPub", "timestamp"],
+    keyPath: "coinPub",
+    versionAdded: 11,
   }),
   coins: describeStore(
     "coins",
diff --git a/packages/taler-wallet-core/src/deposits.ts 
b/packages/taler-wallet-core/src/deposits.ts
index 23b52ac5c..06b57fc79 100644
--- a/packages/taler-wallet-core/src/deposits.ts
+++ b/packages/taler-wallet-core/src/deposits.ts
@@ -983,6 +983,7 @@ async function processDepositGroupPendingDeposit(
     const transitionDone = await wex.db.runReadWriteTx(
       {
         storeNames: [
+          "contractTerms",
           "exchanges",
           "exchangeDetails",
           "depositGroups",
@@ -1001,6 +1002,14 @@ async function processDepositGroupPendingDeposit(
         if (dg.statusPerCoin) {
           return false;
         }
+
+        const contractTermsRec = tx.contractTerms.get(
+          depositGroup.contractTermsHash,
+        );
+        if (!contractTermsRec) {
+          throw Error("contract terms for deposit not found in database");
+        }
+
         const payCoinSel = await selectPayCoinsInTx(wex, tx, {
           restrictExchanges: {
             auditors: [],
@@ -1044,7 +1053,7 @@ async function processDepositGroupPendingDeposit(
         );
         await tx.depositGroups.put(dg);
         await spendCoins(wex, tx, {
-          allocationId: transactionId,
+          transactionId,
           coinPubs: dg.payCoinSelection.coinPubs,
           contributions: dg.payCoinSelection.coinContributions.map((x) =>
             Amounts.parseOrThrow(x),
@@ -1622,7 +1631,7 @@ export async function createDepositGroup(
     async (tx) => {
       if (depositGroup.payCoinSelection) {
         await spendCoins(wex, tx, {
-          allocationId: transactionId,
+          transactionId,
           coinPubs: depositGroup.payCoinSelection.coinPubs,
           contributions: depositGroup.payCoinSelection.coinContributions.map(
             (x) => Amounts.parseOrThrow(x),
diff --git a/packages/taler-wallet-core/src/pay-merchant.ts 
b/packages/taler-wallet-core/src/pay-merchant.ts
index 993b12dd1..37faae686 100644
--- a/packages/taler-wallet-core/src/pay-merchant.ts
+++ b/packages/taler-wallet-core/src/pay-merchant.ts
@@ -1131,6 +1131,8 @@ async function handleInsufficientFunds(
 ): Promise<void> {
   logger.trace("handling insufficient funds, trying to re-select coins");
 
+  const ctx = new PayMerchantTransactionContext(wex, proposalId);
+
   const proposal = await wex.db.runReadOnlyTx(
     { storeNames: ["purchases"] },
     async (tx) => {
@@ -1247,11 +1249,7 @@ async function handleInsufficientFunds(
       payInfo.payCoinSelectionUid = encodeCrock(getRandomBytes(32));
       await tx.purchases.put(p);
       await spendCoins(wex, tx, {
-        // allocationId: `txn:proposal:${p.proposalId}`,
-        allocationId: constructTransactionIdentifier({
-          tag: TransactionType.Payment,
-          proposalId: proposalId,
-        }),
+        transactionId: ctx.transactionId,
         coinPubs: payInfo.payCoinSelection.coinPubs,
         contributions: payInfo.payCoinSelection.coinContributions.map((x) =>
           Amounts.parseOrThrow(x),
@@ -2049,11 +2047,7 @@ export async function confirmPay(
           if (p.payInfo.payCoinSelection) {
             const sel = p.payInfo.payCoinSelection;
             await spendCoins(wex, tx, {
-              //`txn:proposal:${p.proposalId}`
-              allocationId: constructTransactionIdentifier({
-                tag: TransactionType.Payment,
-                proposalId: proposalId,
-              }),
+              transactionId: transactionId as TransactionIdStr,
               coinPubs: sel.coinPubs,
               contributions: sel.coinContributions.map((x) =>
                 Amounts.parseOrThrow(x),
@@ -2308,11 +2302,7 @@ async function processPurchasePay(
             await tx.purchases.put(p);
 
             await spendCoins(wex, tx, {
-              //`txn:proposal:${p.proposalId}`
-              allocationId: constructTransactionIdentifier({
-                tag: TransactionType.Payment,
-                proposalId: proposalId,
-              }),
+              transactionId: ctx.transactionId,
               coinPubs: selectCoinsResult.coinSel.coins.map((x) => x.coinPub),
               contributions: selectCoinsResult.coinSel.coins.map((x) =>
                 Amounts.parseOrThrow(x.contribution),
diff --git a/packages/taler-wallet-core/src/pay-peer-pull-debit.ts 
b/packages/taler-wallet-core/src/pay-peer-pull-debit.ts
index e9be15026..42b777e38 100644
--- a/packages/taler-wallet-core/src/pay-peer-pull-debit.ts
+++ b/packages/taler-wallet-core/src/pay-peer-pull-debit.ts
@@ -496,11 +496,7 @@ async function processPeerPullDebitPendingDeposit(
           return false;
         }
         await spendCoins(wex, tx, {
-          // allocationId: `txn:peer-pull-debit:${req.peerPullDebitId}`,
-          allocationId: constructTransactionIdentifier({
-            tag: TransactionType.PeerPullDebit,
-            peerPullDebitId,
-          }),
+          transactionId: ctx.transactionId,
           coinPubs: coinSelRes.result.coins.map((x) => x.coinPub),
           contributions: coinSelRes.result.coins.map((x) =>
             Amounts.parseOrThrow(x.contribution),
@@ -697,6 +693,9 @@ export async function confirmPeerPullDebit(
     );
   }
 
+  const ctx = new PeerPullDebitTransactionContext(wex, peerPullDebitId);
+  const transactionId = ctx.transactionId;
+
   const instructedAmount = Amounts.parseOrThrow(peerPullInc.amount);
 
   const coinSelRes = await selectPeerCoins(wex, {
@@ -752,11 +751,7 @@ export async function confirmPeerPullDebit(
       }
       if (coinSelRes.type == "success") {
         await spendCoins(wex, tx, {
-          // allocationId: `txn:peer-pull-debit:${req.peerPullDebitId}`,
-          allocationId: constructTransactionIdentifier({
-            tag: TransactionType.PeerPullDebit,
-            peerPullDebitId,
-          }),
+          transactionId,
           coinPubs: coinSelRes.result.coins.map((x) => x.coinPub),
           contributions: coinSelRes.result.coins.map((x) =>
             Amounts.parseOrThrow(x.contribution),
@@ -774,10 +769,6 @@ export async function confirmPeerPullDebit(
     },
   );
 
-  const ctx = new PeerPullDebitTransactionContext(wex, peerPullDebitId);
-
-  const transactionId = ctx.transactionId;
-
   wex.ws.notify({
     type: NotificationType.BalanceChange,
     hintTransactionId: transactionId,
diff --git a/packages/taler-wallet-core/src/pay-peer-push-debit.ts 
b/packages/taler-wallet-core/src/pay-peer-push-debit.ts
index 9c31de06a..6ce426bb0 100644
--- a/packages/taler-wallet-core/src/pay-peer-push-debit.ts
+++ b/packages/taler-wallet-core/src/pay-peer-push-debit.ts
@@ -543,10 +543,7 @@ async function processPeerPushDebitCreateReserve(
         // we might want to mark the coins as used and spend them
         // after we've been able to create the purse.
         await spendCoins(wex, tx, {
-          allocationId: constructTransactionIdentifier({
-            tag: TransactionType.PeerPushDebit,
-            pursePub,
-          }),
+          transactionId: ctx.transactionId,
           coinPubs: coinSelRes.result.coins.map((x) => x.coinPub),
           contributions: coinSelRes.result.coins.map((x) =>
             Amounts.parseOrThrow(x.contribution),
@@ -1170,10 +1167,7 @@ export async function initiatePeerPushDebit(
         // we might want to mark the coins as used and spend them
         // after we've been able to create the purse.
         await spendCoins(wex, tx, {
-          allocationId: constructTransactionIdentifier({
-            tag: TransactionType.PeerPushDebit,
-            pursePub: pursePair.pub,
-          }),
+          transactionId: ctx.transactionId,
           coinPubs: coinSelRes.result.coins.map((x) => x.coinPub),
           contributions: coinSelRes.result.coins.map((x) =>
             Amounts.parseOrThrow(x.contribution),
diff --git a/packages/taler-wallet-core/src/recoup.ts 
b/packages/taler-wallet-core/src/recoup.ts
index be5731b0b..9adc5e2ad 100644
--- a/packages/taler-wallet-core/src/recoup.ts
+++ b/packages/taler-wallet-core/src/recoup.ts
@@ -199,24 +199,20 @@ async function recoupRefreshCoin(
         revokedCoin.exchangeBaseUrl,
         revokedCoin.denomPubHash,
       );
-      checkDbInvariant(!!oldCoinDenom, `no denom for coin, hash 
${oldCoin.denomPubHash}`);
-      checkDbInvariant(!!revokedCoinDenom, `no revoked denom for coin, hash 
${revokedCoin.denomPubHash}`);
+      checkDbInvariant(
+        !!oldCoinDenom,
+        `no denom for coin, hash ${oldCoin.denomPubHash}`,
+      );
+      checkDbInvariant(
+        !!revokedCoinDenom,
+        `no revoked denom for coin, hash ${revokedCoin.denomPubHash}`,
+      );
       revokedCoin.status = CoinStatus.Dormant;
-      if (!revokedCoin.spendAllocation) {
-        // We don't know what happened to this coin
-        logger.error(
-          `can't refresh-recoup coin ${revokedCoin.coinPub}, no 
spendAllocation known`,
-        );
-      } else {
-        let residualAmount = Amounts.sub(
-          revokedCoinDenom.value,
-          revokedCoin.spendAllocation.amount,
-        ).amount;
-        recoupGroup.scheduleRefreshCoins.push({
-          coinPub: oldCoin.coinPub,
-          amount: Amounts.stringify(residualAmount),
-        });
-      }
+      // FIXME: Schedule recoup for the sum of refreshes, based on the coin 
event history.
+      // recoupGroup.scheduleRefreshCoins.push({
+      //   coinPub: oldCoin.coinPub,
+      //   amount: Amounts.stringify(refreshAmount),
+      // });
       await tx.coins.put(revokedCoin);
       await tx.coins.put(oldCoin);
       await putGroupAsFinished(wex, tx, recoupGroup, coinIdx);
diff --git a/packages/taler-wallet-core/src/refresh.ts 
b/packages/taler-wallet-core/src/refresh.ts
index 05c65f6b6..cb39e6588 100644
--- a/packages/taler-wallet-core/src/refresh.ts
+++ b/packages/taler-wallet-core/src/refresh.ts
@@ -1211,7 +1211,6 @@ async function refreshReveal(
         coinEvHash: pc.coinEvHash,
         maxAge: pc.maxAge,
         ageCommitmentProof: pc.ageCommitmentProof,
-        spendAllocation: undefined,
       };
 
       coins.push(coin);
@@ -1605,16 +1604,6 @@ async function applyRefreshToOldCoins(
       default:
         assertUnreachable(coin.status);
     }
-    if (!coin.spendAllocation) {
-      coin.spendAllocation = {
-        amount: Amounts.stringify(ocp.amount),
-        // id: `txn:refresh:${refreshGroupId}`,
-        id: constructTransactionIdentifier({
-          tag: TransactionType.Refresh,
-          refreshGroupId,
-        }),
-      };
-    }
     await tx.coins.put(coin);
   }
 }
diff --git a/packages/taler-wallet-core/src/wallet.ts 
b/packages/taler-wallet-core/src/wallet.ts
index 2a84d912d..bc2011883 100644
--- a/packages/taler-wallet-core/src/wallet.ts
+++ b/packages/taler-wallet-core/src/wallet.ts
@@ -557,12 +557,6 @@ async function dumpCoins(wex: WalletExecutionContext): 
Promise<CoinDumpJson> {
           withdrawal_reserve_pub: withdrawalReservePub,
           coin_status: c.status,
           ageCommitmentProof: c.ageCommitmentProof,
-          spend_allocation: c.spendAllocation
-            ? {
-                amount: c.spendAllocation.amount,
-                id: c.spendAllocation.id,
-              }
-            : undefined,
         });
       }
     },
diff --git a/packages/taler-wallet-core/src/withdraw.ts 
b/packages/taler-wallet-core/src/withdraw.ts
index 8bc4aafd1..2af8807cc 100644
--- a/packages/taler-wallet-core/src/withdraw.ts
+++ b/packages/taler-wallet-core/src/withdraw.ts
@@ -1462,7 +1462,6 @@ async function processPlanchetVerifyAndStoreCoin(
     sourceTransactionId: transactionId,
     maxAge: withdrawalGroup.restrictAge ?? AgeRestriction.AGE_UNRESTRICTED,
     ageCommitmentProof: planchet.ageCommitmentProof,
-    spendAllocation: undefined,
   };
 
   const planchetCoinPub = planchet.coinPub;

-- 
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]