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: mark coins as lo


From: gnunet
Subject: [taler-wallet-core] branch master updated: wallet-core: mark coins as lost, test
Date: Sun, 31 Mar 2024 17:53:12 +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 eb2c8d948 wallet-core: mark coins as lost, test
eb2c8d948 is described below

commit eb2c8d948c2b6fc75915b708ad68d53d37032981
Author: Florian Dold <florian@dold.me>
AuthorDate: Sun Mar 31 17:52:57 2024 +0200

    wallet-core: mark coins as lost, test
---
 .../integrationtests/test-exchange-timetravel.ts   |   1 -
 .../integrationtests/test-wallet-denom-expire.ts   | 150 +++++++++++++++++++++
 .../src/integrationtests/testrunner.ts             |   2 +
 packages/taler-util/src/wallet-types.ts            |   5 +
 packages/taler-wallet-core/src/exchanges.ts        |  37 +++--
 packages/taler-wallet-core/src/refresh.ts          |   2 +
 6 files changed, 186 insertions(+), 11 deletions(-)

diff --git 
a/packages/taler-harness/src/integrationtests/test-exchange-timetravel.ts 
b/packages/taler-harness/src/integrationtests/test-exchange-timetravel.ts
index 74ef64234..714a7f879 100644
--- a/packages/taler-harness/src/integrationtests/test-exchange-timetravel.ts
+++ b/packages/taler-harness/src/integrationtests/test-exchange-timetravel.ts
@@ -38,7 +38,6 @@ import {
   GlobalTestState,
   MerchantService,
   setupDb,
-  WalletCli,
 } from "../harness/harness.js";
 import {
   applyTimeTravelV2,
diff --git 
a/packages/taler-harness/src/integrationtests/test-wallet-denom-expire.ts 
b/packages/taler-harness/src/integrationtests/test-wallet-denom-expire.ts
new file mode 100644
index 000000000..e04aea708
--- /dev/null
+++ b/packages/taler-harness/src/integrationtests/test-wallet-denom-expire.ts
@@ -0,0 +1,150 @@
+/*
+ This file is part of GNU Taler
+ (C) 2020 Taler Systems S.A.
+
+ GNU Taler is free software; you can redistribute it and/or modify it under the
+ terms of the GNU General Public License as published by the Free Software
+ Foundation; either version 3, or (at your option) any later version.
+
+ GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along with
+ GNU Taler; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
+ */
+
+/**
+ * Imports.
+ */
+import { Duration, Logger, NotificationType, j2s } from 
"@gnu-taler/taler-util";
+import { WalletApiOperation } from "@gnu-taler/taler-wallet-core";
+import { makeNoFeeCoinConfig } from "../harness/denomStructures.js";
+import {
+  BankService,
+  ExchangeService,
+  GlobalTestState,
+  MerchantService,
+  generateRandomPayto,
+  setupDb,
+} from "../harness/harness.js";
+import {
+  applyTimeTravelV2,
+  createWalletDaemonWithClient,
+  withdrawViaBankV2,
+} from "../harness/helpers.js";
+
+const logger = new Logger("test-exchange-timetravel.ts");
+
+/**
+ * Test how the wallet handles an expired denomination.
+ */
+export async function runWalletDenomExpireTest(t: GlobalTestState) {
+  // Set up test environment
+
+  const db = await setupDb(t);
+
+  const bank = await BankService.create(t, {
+    allowRegistrations: true,
+    currency: "TESTKUDOS",
+    database: db.connStr,
+    httpPort: 8082,
+  });
+
+  const exchange = ExchangeService.create(t, {
+    name: "testexchange-1",
+    currency: "TESTKUDOS",
+    httpPort: 8081,
+    database: db.connStr,
+  });
+
+  const merchant = await MerchantService.create(t, {
+    name: "testmerchant-1",
+    currency: "TESTKUDOS",
+    httpPort: 8083,
+    database: db.connStr,
+  });
+
+  const exchangeBankAccount = await bank.createExchangeAccount(
+    "myexchange",
+    "x",
+  );
+  exchange.addBankAccount("1", exchangeBankAccount);
+
+  bank.setSuggestedExchange(exchange, exchangeBankAccount.accountPaytoUri);
+
+  await bank.start();
+
+  await bank.pingUntilAvailable();
+
+  exchange.addCoinConfigList(makeNoFeeCoinConfig("TESTKUDOS"));
+
+  await exchange.start();
+  await exchange.pingUntilAvailable();
+
+  merchant.addExchange(exchange);
+
+  await merchant.start();
+  await merchant.pingUntilAvailable();
+
+  await merchant.addInstanceWithWireAccount({
+    id: "default",
+    name: "Default Instance",
+    paytoUris: [generateRandomPayto("merchant-default")],
+  });
+
+  await merchant.addInstanceWithWireAccount({
+    id: "minst1",
+    name: "minst1",
+    paytoUris: [generateRandomPayto("minst1")],
+  });
+
+  console.log("setup done!");
+
+  const { walletClient } = await createWalletDaemonWithClient(t, {
+    name: "default",
+  });
+
+  // Withdraw digital cash into the wallet.
+
+  const wres = await withdrawViaBankV2(t, {
+    walletClient,
+    bank,
+    exchange,
+    amount: "TESTKUDOS:15",
+  });
+  await wres.withdrawalFinishedCond;
+
+  const denomLossCond = walletClient.waitForNotificationCond((n) => {
+    return (
+      n.type === NotificationType.TransactionStateTransition &&
+      n.transactionId.startsWith("txn:denom-loss:")
+    );
+  });
+
+  // Travel into the future, the deposit expiration is two years
+  // into the future.
+  console.log("applying first time travel");
+  await applyTimeTravelV2(
+    Duration.toMilliseconds(Duration.fromSpec({ days: 400 })),
+    {
+      walletClient,
+      exchange,
+      merchant,
+    },
+  );
+
+  // Should be detected automatically, as exchange entry is surely outdated.
+  await denomLossCond;
+
+  const bal = await walletClient.call(WalletApiOperation.GetBalances, {});
+  console.log(`balances: ${j2s(bal)}`);
+
+  const txns = await walletClient.call(WalletApiOperation.GetTransactions, {
+    sort: "stable-ascending",
+    includeRefreshes: true,
+  });
+  console.log(`transactions: ${j2s(txns)}`);
+}
+
+runWalletDenomExpireTest.suites = ["exchange"];
diff --git a/packages/taler-harness/src/integrationtests/testrunner.ts 
b/packages/taler-harness/src/integrationtests/testrunner.ts
index 566350770..380251b76 100644
--- a/packages/taler-harness/src/integrationtests/testrunner.ts
+++ b/packages/taler-harness/src/integrationtests/testrunner.ts
@@ -95,6 +95,7 @@ import { runWalletConfigTest } from "./test-wallet-config.js";
 import { runWalletCryptoWorkerTest } from "./test-wallet-cryptoworker.js";
 import { runWalletDblessTest } from "./test-wallet-dbless.js";
 import { runWalletDd48Test } from "./test-wallet-dd48.js";
+import { runWalletDenomExpireTest } from "./test-wallet-denom-expire.js";
 import { runWalletDevExperimentsTest } from "./test-wallet-dev-experiments.js";
 import { runWalletGenDbTest } from "./test-wallet-gendb.js";
 import { runWalletInsufficientBalanceTest } from 
"./test-wallet-insufficient-balance.js";
@@ -210,6 +211,7 @@ const allTests: TestMainFunction[] = [
   runWalletInsufficientBalanceTest,
   runWalletWirefeesTest,
   runDenomLostTest,
+  runWalletDenomExpireTest,
 ];
 
 export interface TestRunSpec {
diff --git a/packages/taler-util/src/wallet-types.ts 
b/packages/taler-util/src/wallet-types.ts
index 7b6da8a40..c179a2aec 100644
--- a/packages/taler-util/src/wallet-types.ts
+++ b/packages/taler-util/src/wallet-types.ts
@@ -578,6 +578,11 @@ export enum CoinStatus {
    */
   Fresh = "fresh",
 
+  /**
+   * Coin was lost as the denomination is not useable anymore.
+   */
+  DenomLoss = "denom-loss",
+
   /**
    * Fresh, but currently marked as "suspended", thus won't be used
    * for spending.  Used for testing.
diff --git a/packages/taler-wallet-core/src/exchanges.ts 
b/packages/taler-wallet-core/src/exchanges.ts
index 48d8d4972..7fb387a9e 100644
--- a/packages/taler-wallet-core/src/exchanges.ts
+++ b/packages/taler-wallet-core/src/exchanges.ts
@@ -1697,7 +1697,7 @@ interface DenomLossResult {
 async function handleDenomLoss(
   wex: WalletExecutionContext,
   tx: WalletDbReadWriteTransaction<
-    ["coinAvailability", "denominations", "denomLossEvents"]
+    ["coinAvailability", "denominations", "denomLossEvents", "coins"]
   >,
   currency: string,
   exchangeBaseUrl: string,
@@ -1721,6 +1721,9 @@ async function handleDenomLoss(
     }
     const n = coinAv.freshCoinCount;
     const denom = await tx.denominations.get(coinAv.denomPubHash);
+    const timestampExpireDeposit = !denom
+      ? undefined
+      : timestampAbsoluteFromDb(denom.stampExpireDeposit);
     if (!denom) {
       // Remove availability
       coinAv.freshCoinCount = 0;
@@ -1729,9 +1732,7 @@ async function handleDenomLoss(
       denomsVanished.push(coinAv.denomPubHash);
       const total = Amount.from(coinAv.value).mult(n);
       amountVanished = amountVanished.add(total);
-      continue;
-    }
-    if (!denom.isOffered) {
+    } else if (!denom.isOffered) {
       // Remove availability
       coinAv.freshCoinCount = 0;
       coinAv.visibleCoinCount = 0;
@@ -1739,12 +1740,10 @@ async function handleDenomLoss(
       denomsUnoffered.push(coinAv.denomPubHash);
       const total = Amount.from(coinAv.value).mult(n);
       amountUnoffered = amountUnoffered.add(total);
-      continue;
-    }
-    const timestampExpireDeposit = timestampAbsoluteFromDb(
-      denom.stampExpireDeposit,
-    );
-    if (AbsoluteTime.isExpired(timestampExpireDeposit)) {
+    } else if (
+      timestampExpireDeposit &&
+      AbsoluteTime.isExpired(timestampExpireDeposit)
+    ) {
       // Remove availability
       coinAv.freshCoinCount = 0;
       coinAv.visibleCoinCount = 0;
@@ -1752,8 +1751,26 @@ async function handleDenomLoss(
       denomsExpired.push(coinAv.denomPubHash);
       const total = Amount.from(coinAv.value).mult(n);
       amountExpired = amountExpired.add(total);
+    } else {
+      // Denomination is still fine!
       continue;
     }
+
+    logger.warn(`denomination ${coinAv.denomPubHash} is a loss`);
+
+    const coins = await tx.coins.indexes.byDenomPubHash.getAll(
+      coinAv.denomPubHash,
+    );
+    for (const coin of coins) {
+      switch (coin.status) {
+        case CoinStatus.Fresh:
+        case CoinStatus.FreshSuspended: {
+          coin.status = CoinStatus.DenomLoss;
+          await tx.coins.put(coin);
+          break;
+        }
+      }
+    }
   }
 
   if (denomsVanished.length > 0) {
diff --git a/packages/taler-wallet-core/src/refresh.ts 
b/packages/taler-wallet-core/src/refresh.ts
index 7c9ec84bd..516d5e3da 100644
--- a/packages/taler-wallet-core/src/refresh.ts
+++ b/packages/taler-wallet-core/src/refresh.ts
@@ -1311,6 +1311,8 @@ async function applyRefresh(
         coin.status = CoinStatus.Dormant;
         break;
       }
+      case CoinStatus.DenomLoss:
+        break;
       default:
         assertUnreachable(coin.status);
     }

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