gnunet-svn
[Top][All Lists]
Advanced

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

[taler-wallet-core] 01/02: wallet-core: implement and test lost flag for


From: gnunet
Subject: [taler-wallet-core] 01/02: wallet-core: implement and test lost flag for denominations
Date: Thu, 07 Mar 2024 17:53:41 +0100

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

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

commit c22b13eebe0577c2b948a99e42670580d49d60ce
Author: Florian Dold <florian@dold.me>
AuthorDate: Thu Mar 7 17:28:14 2024 +0100

    wallet-core: implement and test lost flag for denominations
---
 .../src/integrationtests/test-denom-lost.ts        | 81 ++++++++++++++++++++++
 .../src/integrationtests/testrunner.ts             |  2 +
 packages/taler-util/src/wallet-types.ts            | 16 +++++
 packages/taler-wallet-core/src/db.ts               |  7 ++
 packages/taler-wallet-core/src/denominations.ts    |  5 +-
 packages/taler-wallet-core/src/exchanges.ts        | 11 +++
 packages/taler-wallet-core/src/wallet-api-types.ts | 13 ++++
 packages/taler-wallet-core/src/wallet.ts           | 25 +++++++
 8 files changed, 157 insertions(+), 3 deletions(-)

diff --git a/packages/taler-harness/src/integrationtests/test-denom-lost.ts 
b/packages/taler-harness/src/integrationtests/test-denom-lost.ts
new file mode 100644
index 000000000..307ae352a
--- /dev/null
+++ b/packages/taler-harness/src/integrationtests/test-denom-lost.ts
@@ -0,0 +1,81 @@
+/*
+ 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 { WalletApiOperation } from "@gnu-taler/taler-wallet-core";
+import { GlobalTestState } from "../harness/harness.js";
+import {
+  createSimpleTestkudosEnvironmentV2,
+  withdrawViaBankV2,
+} from "../harness/helpers.js";
+
+/**
+ * Run test for refreshe after a payment.
+ */
+export async function runDenomLostTest(t: GlobalTestState) {
+  // Set up test environment
+
+  const { walletClient, bank, exchange, merchant } =
+    await createSimpleTestkudosEnvironmentV2(t);
+
+  // Withdraw digital cash into the wallet.
+
+  const wres = await withdrawViaBankV2(t, {
+    walletClient,
+    bank,
+    exchange,
+    amount: "TESTKUDOS:20",
+  });
+
+  await wres.withdrawalFinishedCond;
+
+  const dsBefore = await walletClient.call(
+    WalletApiOperation.TestingGetDenomStats,
+    {
+      exchangeBaseUrl: exchange.baseUrl,
+    },
+  );
+
+  t.assertDeepEqual(dsBefore.numLost, 0);
+  t.assertDeepEqual(dsBefore.numOffered, dsBefore.numKnown);
+
+  await exchange.stop();
+
+  await exchange.purgeSecmodKeys();
+
+  await exchange.start();
+
+  await walletClient.call(WalletApiOperation.UpdateExchangeEntry, {
+    exchangeBaseUrl: exchange.baseUrl,
+    force: true,
+  });
+
+  const dsAfter = await walletClient.call(
+    WalletApiOperation.TestingGetDenomStats,
+    {
+      exchangeBaseUrl: exchange.baseUrl,
+    },
+  );
+
+  // All previous denominations were lost
+  t.assertDeepEqual(dsBefore.numOffered, dsAfter.numLost);
+  // But we have new ones!
+  t.assertTrue(dsAfter.numKnown > dsBefore.numKnown);
+}
+
+runDenomLostTest.suites = ["wallet"];
diff --git a/packages/taler-harness/src/integrationtests/testrunner.ts 
b/packages/taler-harness/src/integrationtests/testrunner.ts
index a294b27f4..566350770 100644
--- a/packages/taler-harness/src/integrationtests/testrunner.ts
+++ b/packages/taler-harness/src/integrationtests/testrunner.ts
@@ -36,6 +36,7 @@ import { runBankApiTest } from "./test-bank-api.js";
 import { runClaimLoopTest } from "./test-claim-loop.js";
 import { runClauseSchnorrTest } from "./test-clause-schnorr.js";
 import { runCurrencyScopeTest } from "./test-currency-scope.js";
+import { runDenomLostTest } from "./test-denom-lost.js";
 import { runDenomUnofferedTest } from "./test-denom-unoffered.js";
 import { runDepositTest } from "./test-deposit.js";
 import { runExchangeDepositTest } from "./test-exchange-deposit.js";
@@ -208,6 +209,7 @@ const allTests: TestMainFunction[] = [
   runWalletBalanceZeroTest,
   runWalletInsufficientBalanceTest,
   runWalletWirefeesTest,
+  runDenomLostTest,
 ];
 
 export interface TestRunSpec {
diff --git a/packages/taler-util/src/wallet-types.ts 
b/packages/taler-util/src/wallet-types.ts
index 69811969c..0d2713fdd 100644
--- a/packages/taler-util/src/wallet-types.ts
+++ b/packages/taler-util/src/wallet-types.ts
@@ -2982,6 +2982,22 @@ export interface TestingWaitTransactionRequest {
   txState: TransactionState;
 }
 
+export interface TestingGetDenomStatsRequest {
+  exchangeBaseUrl: string;
+}
+
+export interface TestingGetDenomStatsResponse {
+  numKnown: number;
+  numOffered: number;
+  numLost: number;
+}
+
+export const codecForTestingGetDenomStatsRequest =
+  (): Codec<TestingGetDenomStatsRequest> =>
+    buildCodecForObject<TestingGetDenomStatsRequest>()
+      .property("exchangeBaseUrl", codecForString())
+      .build("TestingGetDenomStatsRequest");
+
 export interface WithdrawalExchangeAccountDetails {
   /**
    * Payto URI to credit the exchange.
diff --git a/packages/taler-wallet-core/src/db.ts 
b/packages/taler-wallet-core/src/db.ts
index 14621c2d5..b59efe034 100644
--- a/packages/taler-wallet-core/src/db.ts
+++ b/packages/taler-wallet-core/src/db.ts
@@ -485,6 +485,13 @@ export interface DenominationRecord {
    */
   isRevoked: boolean;
 
+  /**
+   * If set to true, the exchange announced that the private key for this
+   * denomination is lost.  Thus it can't be used to sign new coins
+   * during withdrawal/refresh/..., but the coins can still be spent.
+   */
+  isLost?: boolean;
+
   /**
    * Base URL of the exchange.
    */
diff --git a/packages/taler-wallet-core/src/denominations.ts 
b/packages/taler-wallet-core/src/denominations.ts
index a539918de..d41307d5d 100644
--- a/packages/taler-wallet-core/src/denominations.ts
+++ b/packages/taler-wallet-core/src/denominations.ts
@@ -24,7 +24,6 @@ import {
   AmountString,
   DenominationInfo,
   Duration,
-  durationFromSpec,
   FeeDescription,
   FeeDescriptionPair,
   TalerProtocolTimestamp,
@@ -471,10 +470,10 @@ export function isWithdrawableDenom(
   } else {
     lastPossibleWithdraw = AbsoluteTime.subtractDuraction(
       withdrawExpire,
-      durationFromSpec({ minutes: 5 }),
+      Duration.fromSpec({ minutes: 5 }),
     );
   }
   const remaining = Duration.getRemaining(lastPossibleWithdraw, now);
   const stillOkay = remaining.d_ms !== 0;
-  return started && stillOkay && !d.isRevoked && d.isOffered;
+  return started && stillOkay && !d.isRevoked && d.isOffered && !d.isLost;
 }
diff --git a/packages/taler-wallet-core/src/exchanges.ts 
b/packages/taler-wallet-core/src/exchanges.ts
index 335caff62..c44178de8 100644
--- a/packages/taler-wallet-core/src/exchanges.ts
+++ b/packages/taler-wallet-core/src/exchanges.ts
@@ -779,6 +779,7 @@ async function downloadExchangeKeysInfo(
             exchangeMasterPub: exchangeKeysJsonUnchecked.master_public_key,
             isOffered: true,
             isRevoked: false,
+            isLost: denomIn.lost ?? false,
             value: Amounts.stringify(value),
             currency: value.currency,
             stampExpireDeposit: timestampProtocolToDb(
@@ -1432,6 +1433,16 @@ export async function updateExchangeFromUrlHandler(
         ]);
         if (oldDenom) {
           // FIXME: Do consistency check, report to auditor if necessary.
+          // See https://bugs.taler.net/n/8594
+
+          // Mark lost denominations as lost.
+          if (currentDenom.isLost && !oldDenom.isLost) {
+            logger.warn(
+              `marking denomination ${currentDenom.denomPubHash} of 
${exchangeBaseUrl} as lost`,
+            );
+            oldDenom.isLost = true;
+            await tx.denominations.put(currentDenom);
+          }
         } else {
           await tx.denominations.put(currentDenom);
         }
diff --git a/packages/taler-wallet-core/src/wallet-api-types.ts 
b/packages/taler-wallet-core/src/wallet-api-types.ts
index ace702e88..4f4b24b62 100644
--- a/packages/taler-wallet-core/src/wallet-api-types.ts
+++ b/packages/taler-wallet-core/src/wallet-api-types.ts
@@ -117,6 +117,8 @@ import {
   StoredBackupList,
   TestPayArgs,
   TestPayResult,
+  TestingGetDenomStatsRequest,
+  TestingGetDenomStatsResponse,
   TestingListTasksForTransactionRequest,
   TestingListTasksForTransactionsResponse,
   TestingSetTimetravelRequest,
@@ -255,6 +257,7 @@ export enum WalletApiOperation {
   RemoveGlobalCurrencyAuditor = "removeGlobalCurrencyAuditor",
   ListAssociatedRefreshes = "listAssociatedRefreshes",
   TestingListTaskForTransaction = "testingListTasksForTransaction",
+  TestingGetDenomStats = "testingGetDenomStats",
 }
 
 // group: Initialization
@@ -1113,6 +1116,15 @@ export type TestingWaitTransactionStateOp = {
   response: EmptyObject;
 };
 
+/**
+ * Get stats about an exchange denomination.
+ */
+export type TestingGetDenomStatsOp = {
+  op: WalletApiOperation.TestingGetDenomStats;
+  request: TestingGetDenomStatsRequest;
+  response: TestingGetDenomStatsResponse;
+};
+
 /**
  * Set a coin as (un-)suspended.
  * Suspended coins won't be used for payments.
@@ -1238,6 +1250,7 @@ export type WalletOperations = {
   [WalletApiOperation.RemoveGlobalCurrencyExchange]: 
RemoveGlobalCurrencyExchangeOp;
   [WalletApiOperation.ListAssociatedRefreshes]: ListAssociatedRefreshesOp;
   [WalletApiOperation.TestingListTaskForTransaction]: 
TestingListTasksForTransactionOp;
+  [WalletApiOperation.TestingGetDenomStats]: TestingGetDenomStatsOp;
 };
 
 export type WalletCoreRequestType<
diff --git a/packages/taler-wallet-core/src/wallet.ts 
b/packages/taler-wallet-core/src/wallet.ts
index 8c9eee009..46f58ec81 100644
--- a/packages/taler-wallet-core/src/wallet.ts
+++ b/packages/taler-wallet-core/src/wallet.ts
@@ -57,6 +57,7 @@ import {
   TalerErrorCode,
   TalerProtocolTimestamp,
   TalerUriAction,
+  TestingGetDenomStatsResponse,
   TestingListTasksForTransactionsResponse,
   TestingWaitTransactionRequest,
   TimerAPI,
@@ -126,6 +127,7 @@ import {
   codecForStartRefundQueryRequest,
   codecForSuspendTransaction,
   codecForTestPayArgs,
+  codecForTestingGetDenomStatsRequest,
   codecForTestingListTasksForTransactionRequest,
   codecForTestingSetTimetravelRequest,
   codecForTransactionByIdRequest,
@@ -799,6 +801,29 @@ async function dispatchRequestInternal<Op extends 
WalletApiOperation>(
       });
       return {};
     }
+    case WalletApiOperation.TestingGetDenomStats: {
+      const req = codecForTestingGetDenomStatsRequest().decode(payload);
+      const denomStats: TestingGetDenomStatsResponse = {
+        numKnown: 0,
+        numLost: 0,
+        numOffered: 0,
+      };
+      await wex.db.runReadOnlyTx(["denominations"], async (tx) => {
+        const denoms = await tx.denominations.indexes.byExchangeBaseUrl.getAll(
+          req.exchangeBaseUrl,
+        );
+        for (const d of denoms) {
+          denomStats.numKnown++;
+          if (d.isOffered) {
+            denomStats.numOffered++;
+          }
+          if (d.isLost) {
+            denomStats.numLost++;
+          }
+        }
+      });
+      return denomStats;
+    }
     case WalletApiOperation.ListExchanges: {
       return await listExchanges(wex);
     }

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