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: support for with


From: gnunet
Subject: [taler-wallet-core] branch master updated: wallet-core: support for withdrawals with forced reserve key
Date: Tue, 23 Apr 2024 12:49:47 +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 666b76776 wallet-core: support for withdrawals with forced reserve key
666b76776 is described below

commit 666b767766ef299bd58655c55ece6d4a82c3e947
Author: Florian Dold <florian@dold.me>
AuthorDate: Tue Apr 23 12:49:42 2024 +0200

    wallet-core: support for withdrawals with forced reserve key
---
 packages/taler-harness/src/bench1.ts               |  4 ++--
 packages/taler-harness/src/bench3.ts               |  4 ++--
 packages/taler-util/src/taler-types.ts             |  1 +
 packages/taler-util/src/wallet-types.ts            | 11 ++++++++++
 packages/taler-wallet-cli/src/index.ts             | 25 ++++++++++++++++++----
 .../taler-wallet-core/src/observable-wrappers.ts   |  4 ++++
 packages/taler-wallet-core/src/shepherd.ts         | 23 ++++++++++++++------
 packages/taler-wallet-core/src/wallet-api-types.ts |  8 +++++++
 packages/taler-wallet-core/src/wallet.ts           | 13 +++++++----
 packages/taler-wallet-core/src/withdraw.ts         | 19 +++++++++++++---
 .../taler-wallet-webextension/src/wxBackend.ts     |  2 +-
 11 files changed, 91 insertions(+), 23 deletions(-)

diff --git a/packages/taler-harness/src/bench1.ts 
b/packages/taler-harness/src/bench1.ts
index 216760260..d260ea731 100644
--- a/packages/taler-harness/src/bench1.ts
+++ b/packages/taler-harness/src/bench1.ts
@@ -74,7 +74,7 @@ export async function runBench1(configJson: any): 
Promise<void> {
     // my assumption is that the in-memory db file gets too large
     if (i % restartWallet == 0) {
       if (Object.keys(wallet).length !== 0) {
-        wallet.stop();
+        await wallet.client.call(WalletApiOperation.Shutdown, {});
         console.log("wallet DB stats", j2s(getDbStats!()));
       }
 
@@ -127,7 +127,7 @@ export async function runBench1(configJson: any): 
Promise<void> {
     }
   }
 
-  wallet.stop();
+  await wallet.client.call(WalletApiOperation.Shutdown, {});
   console.log("wallet DB stats", j2s(getDbStats!()));
 }
 
diff --git a/packages/taler-harness/src/bench3.ts 
b/packages/taler-harness/src/bench3.ts
index a5bc094df..ddf763c5b 100644
--- a/packages/taler-harness/src/bench3.ts
+++ b/packages/taler-harness/src/bench3.ts
@@ -85,7 +85,7 @@ export async function runBench3(configJson: any): 
Promise<void> {
     // my assumption is that the in-memory db file gets too large
     if (i % restartWallet == 0) {
       if (Object.keys(wallet).length !== 0) {
-        wallet.stop();
+        await wallet.client.call(WalletApiOperation.Shutdown, {});
         console.log("wallet DB stats", j2s(getDbStats!()));
       }
 
@@ -139,7 +139,7 @@ export async function runBench3(configJson: any): 
Promise<void> {
     }
   }
 
-  wallet.stop();
+  await wallet.client.call(WalletApiOperation.Shutdown, {});
   console.log("wallet DB stats", j2s(getDbStats!()));
 }
 
diff --git a/packages/taler-util/src/taler-types.ts 
b/packages/taler-util/src/taler-types.ts
index 2b8e55e38..392e7149c 100644
--- a/packages/taler-util/src/taler-types.ts
+++ b/packages/taler-util/src/taler-types.ts
@@ -1335,6 +1335,7 @@ export type AmountString = string & { [__amount_str]: 
true };
 export type Base32String = string;
 export type EddsaSignatureString = string;
 export type EddsaPublicKeyString = string;
+export type EddsaPrivateKeyString = string;
 export type CoinPublicKeyString = string;
 
 export const codecForDenomination = (): Codec<ExchangeDenomination> =>
diff --git a/packages/taler-util/src/wallet-types.ts 
b/packages/taler-util/src/wallet-types.ts
index 0564c45f7..9575e6d7d 100644
--- a/packages/taler-util/src/wallet-types.ts
+++ b/packages/taler-util/src/wallet-types.ts
@@ -62,6 +62,7 @@ import {
   CoinEnvelope,
   DenomKeyType,
   DenominationPubKey,
+  EddsaPrivateKeyString,
   ExchangeAuditor,
   ExchangeWireAccount,
   InternationalizedString,
@@ -1843,6 +1844,15 @@ export interface AcceptManualWithdrawalRequest {
   exchangeBaseUrl: string;
   amount: AmountString;
   restrictAge?: number;
+
+  /**
+   * Instead of generating a fresh, random reserve key pair,
+   * use the provided reserve private key.
+   *
+   * Use with caution.  Usage of this field may be restricted
+   * to developer mode.
+   */
+  forceReservePriv?: EddsaPrivateKeyString;
 }
 
 export const codecForAcceptManualWithdrawalRequest =
@@ -1851,6 +1861,7 @@ export const codecForAcceptManualWithdrawalRequest =
       .property("exchangeBaseUrl", codecForString())
       .property("amount", codecForAmountString())
       .property("restrictAge", codecOptional(codecForNumber()))
+      .property("forceReservePriv", codecOptional(codecForString()))
       .build("AcceptManualWithdrawalRequest");
 
 export interface GetWithdrawalDetailsForAmountRequest {
diff --git a/packages/taler-wallet-cli/src/index.ts 
b/packages/taler-wallet-cli/src/index.ts
index b85995052..b915de538 100644
--- a/packages/taler-wallet-cli/src/index.ts
+++ b/packages/taler-wallet-cli/src/index.ts
@@ -57,6 +57,7 @@ import { JsonMessage, runRpcServer } from 
"@gnu-taler/taler-util/twrpc";
 import {
   AccessStats,
   createNativeWalletHost2,
+  nativeCrypto,
   Wallet,
   WalletApiOperation,
   WalletCoreApiClient,
@@ -349,7 +350,7 @@ async function withWallet<T>(
       },
     };
     const result = await f(ctx);
-    wh.wallet.stop();
+    await wh.wallet.client.call(WalletApiOperation.Shutdown, {});
     if (process.env.TALER_WALLET_DBSTATS) {
       console.log("database stats:");
       console.log(j2s(wh.getStats()));
@@ -723,6 +724,7 @@ withdrawCli
   .requiredOption("amount", ["--amount"], clk.AMOUNT, {
     help: "Amount to withdraw",
   })
+  .maybeOption("forcedReservePriv", ["--forced-reserve-priv"], clk.STRING, {})
   .maybeOption("restrictAge", ["--restrict-age"], clk.INT)
   .action(async (args) => {
     await withWallet(args, async (wallet) => {
@@ -735,7 +737,7 @@ withdrawCli
           exchangeBaseUrl: exchangeBaseUrl,
         },
       );
-      const acct = d.paytoUris[0];
+      const acct = d.withdrawalAccountsList[0];
       if (!acct) {
         console.log("exchange has no accounts");
         return;
@@ -746,10 +748,11 @@ withdrawCli
           amount,
           exchangeBaseUrl,
           restrictAge: parseInt(String(args.withdrawManually.restrictAge), 10),
+          forceReservePriv: args.withdrawManually.forcedReservePriv,
         },
       );
       const reservePub = resp.reservePub;
-      const completePaytoUri = addPaytoQueryParams(acct, {
+      const completePaytoUri = addPaytoQueryParams(acct.paytoUri, {
         amount: args.withdrawManually.amount,
         message: `Taler top-up ${reservePub}`,
       });
@@ -1171,6 +1174,20 @@ const advancedCli = walletCli.subcommand("advancedArgs", 
"advanced", {
   help: "Subcommands for advanced operations (only use if you know what you're 
doing!).",
 });
 
+advancedCli
+  .subcommand("genReserve", "gen-reserve", {
+    help: "Generate a reserve key pair (not stored in the DB).",
+  })
+  .action(async (args) => {
+    const pair = await nativeCrypto.createEddsaKeypair({});
+    console.log(
+      j2s({
+        reservePub: pair.pub,
+        reservePriv: pair.priv,
+      }),
+    );
+  });
+
 advancedCli
   .subcommand("tasks", "tasks", {
     help: "Show active wallet-core tasks.",
@@ -1322,7 +1339,7 @@ advancedCli
       merchantBaseUrl: "http://localhost:8083/";,
     });
     await wallet.client.call(WalletApiOperation.TestingWaitTasksDone, {});
-    wallet.stop();
+    await wallet.client.call(WalletApiOperation.Shutdown, {});
   });
 
 advancedCli
diff --git a/packages/taler-wallet-core/src/observable-wrappers.ts 
b/packages/taler-wallet-core/src/observable-wrappers.ts
index f09498d95..717de41ca 100644
--- a/packages/taler-wallet-core/src/observable-wrappers.ts
+++ b/packages/taler-wallet-core/src/observable-wrappers.ts
@@ -60,6 +60,10 @@ export class ObservableTaskScheduler implements 
TaskScheduler {
     }
   }
 
+  shutdown(): Promise<void> {
+    return this.impl.shutdown();
+  }
+
   getActiveTasks(): TaskIdStr[] {
     return this.impl.getActiveTasks();
   }
diff --git a/packages/taler-wallet-core/src/shepherd.ts 
b/packages/taler-wallet-core/src/shepherd.ts
index 5e2d23fd9..3b160d97f 100644
--- a/packages/taler-wallet-core/src/shepherd.ts
+++ b/packages/taler-wallet-core/src/shepherd.ts
@@ -149,6 +149,7 @@ export interface TaskScheduler {
   reload(): Promise<void>;
   getActiveTasks(): TaskIdStr[];
   isIdle(): boolean;
+  shutdown(): Promise<void>;
 }
 
 export class TaskSchedulerImpl implements TaskScheduler {
@@ -176,6 +177,14 @@ export class TaskSchedulerImpl implements TaskScheduler {
     return [...this.sheps.keys()];
   }
 
+  async shutdown(): Promise<void> {
+    const tasksIds = [...this.sheps.keys()];
+    logger.info(`Stopping task shepherd.`);
+    for (const taskId of tasksIds) {
+      this.stopShepherdTask(taskId);
+    }
+  }
+
   async ensureRunning(): Promise<void> {
     if (this.isRunning) {
       return;
@@ -193,7 +202,7 @@ export class TaskSchedulerImpl implements TaskScheduler {
         logger.error(`err: ${e}`);
       })
       .then(() => {
-        logger.info("done running task loop");
+        logger.trace("done running task loop");
         this.isRunning = false;
       });
   }
@@ -212,11 +221,11 @@ export class TaskSchedulerImpl implements TaskScheduler {
   }
 
   private async run(): Promise<void> {
-    logger.info("Running task loop.");
-    logger.info(`sheps: ${this.sheps.size}`);
+    logger.trace("Running task loop.");
+    logger.trace(`sheps: ${this.sheps.size}`);
     while (true) {
       if (this.ws.stopped) {
-        logger.info("Breaking out of task loop (wallet stopped).");
+        logger.trace("Breaking out of task loop (wallet stopped).");
         break;
       }
 
@@ -228,7 +237,7 @@ export class TaskSchedulerImpl implements TaskScheduler {
 
       await this.iterCond.wait();
     }
-    logger.info("Done with task loop.");
+    logger.trace("Done with task loop.");
   }
 
   startShepherdTask(taskId: TaskIdStr): void {
@@ -360,11 +369,11 @@ export class TaskSchedulerImpl implements TaskScheduler {
         };
       }
       if (info.cts.token.isCancelled) {
-        logger.info("task cancelled, not processing result");
+        logger.trace("task cancelled, not processing result");
         return;
       }
       if (this.ws.stopped) {
-        logger.info("wallet stopped, not processing result");
+        logger.trace("wallet stopped, not processing result");
         return;
       }
       wex.oc.observe({
diff --git a/packages/taler-wallet-core/src/wallet-api-types.ts 
b/packages/taler-wallet-core/src/wallet-api-types.ts
index ba28c009a..e876d8aea 100644
--- a/packages/taler-wallet-core/src/wallet-api-types.ts
+++ b/packages/taler-wallet-core/src/wallet-api-types.ts
@@ -252,6 +252,7 @@ export enum WalletApiOperation {
   AddGlobalCurrencyAuditor = "addGlobalCurrencyAuditor",
   RemoveGlobalCurrencyAuditor = "removeGlobalCurrencyAuditor",
   ListAssociatedRefreshes = "listAssociatedRefreshes",
+  Shutdown = "shutdown",
   TestingWaitTransactionsFinal = "testingWaitTransactionsFinal",
   TestingWaitRefreshesFinal = "testingWaitRefreshesFinal",
   TestingWaitTransactionState = "testingWaitTransactionState",
@@ -278,6 +279,12 @@ export type InitWalletOp = {
   response: InitResponse;
 };
 
+export type ShutdownOp = {
+  op: WalletApiOperation.Shutdown;
+  request: EmptyObject;
+  response: EmptyObject;
+};
+
 /**
  * Change the configuration of wallet-core.
  *
@@ -1284,6 +1291,7 @@ export type WalletOperations = {
   [WalletApiOperation.TestingListTaskForTransaction]: 
TestingListTasksForTransactionOp;
   [WalletApiOperation.TestingGetDenomStats]: TestingGetDenomStatsOp;
   [WalletApiOperation.TestingPing]: TestingPingOp;
+  [WalletApiOperation.Shutdown]: ShutdownOp;
 };
 
 export type WalletCoreRequestType<
diff --git a/packages/taler-wallet-core/src/wallet.ts 
b/packages/taler-wallet-core/src/wallet.ts
index b59f52840..dd6ce96f4 100644
--- a/packages/taler-wallet-core/src/wallet.ts
+++ b/packages/taler-wallet-core/src/wallet.ts
@@ -145,6 +145,7 @@ import {
   parsePaytoUri,
   parseTalerUri,
   performanceNow,
+  safeStringifyException,
   sampleWalletCoreTransactions,
   setDangerousTimetravel,
   validateIban,
@@ -909,6 +910,7 @@ async function dispatchRequestInternal(
         amount: Amounts.parseOrThrow(req.amount),
         exchangeBaseUrl: req.exchangeBaseUrl,
         restrictAge: req.restrictAge,
+        forceReservePriv: req.forceReservePriv,
       });
       return res;
     }
@@ -1432,6 +1434,10 @@ async function dispatchRequestInternal(
       await applyDevExperiment(wex, req.devExperimentUri);
       return {};
     }
+    case WalletApiOperation.Shutdown: {
+      wex.ws.stop();
+      return {};
+    }
     case WalletApiOperation.GetVersion: {
       return getVersion(wex);
     }
@@ -1700,10 +1706,6 @@ export class Wallet {
     return this.ws.addNotificationListener(f);
   }
 
-  stop(): void {
-    this.ws.stop();
-  }
-
   async handleCoreApiRequest(
     operation: string,
     id: string,
@@ -1952,6 +1954,9 @@ export class InternalWalletState {
     this.stopped = true;
     this.timerGroup.stopCurrentAndFutureTimers();
     this.cryptoDispatcher.stop();
+    this.taskScheduler.shutdown().catch((e) => {
+      logger.warn(`shutdown failed: ${safeStringifyException(e)}`);
+    });
   }
 
   /**
diff --git a/packages/taler-wallet-core/src/withdraw.ts 
b/packages/taler-wallet-core/src/withdraw.ts
index 4936135bd..a55ada796 100644
--- a/packages/taler-wallet-core/src/withdraw.ts
+++ b/packages/taler-wallet-core/src/withdraw.ts
@@ -41,6 +41,7 @@ import {
   DenomSelItem,
   DenomSelectionState,
   Duration,
+  EddsaPrivateKeyString,
   ExchangeBatchWithdrawRequest,
   ExchangeUpdateStatus,
   ExchangeWireAccount,
@@ -3050,6 +3051,7 @@ export async function createManualWithdrawal(
     amount: AmountLike;
     restrictAge?: number;
     forcedDenomSel?: ForcedDenomSel;
+    forceReservePriv?: EddsaPrivateKeyString;
   },
 ): Promise<AcceptManualWithdrawalResult> {
   const { exchangeBaseUrl } = req;
@@ -3061,9 +3063,20 @@ export async function createManualWithdrawal(
       "manual withdrawal with conversion from foreign currency is not yet 
supported",
     );
   }
-  const reserveKeyPair: EddsaKeypair = await wex.cryptoApi.createEddsaKeypair(
-    {},
-  );
+
+  let reserveKeyPair: EddsaKeypair;
+  if (req.forceReservePriv) {
+    const pubResp = await wex.cryptoApi.eddsaGetPublic({
+      priv: req.forceReservePriv,
+    });
+
+    reserveKeyPair = {
+      priv: req.forceReservePriv,
+      pub: pubResp.pub,
+    };
+  } else {
+    reserveKeyPair = await wex.cryptoApi.createEddsaKeypair({});
+  }
 
   const withdrawalAccountsList = await fetchWithdrawalAccountInfo(
     wex,
diff --git a/packages/taler-wallet-webextension/src/wxBackend.ts 
b/packages/taler-wallet-webextension/src/wxBackend.ts
index bf70f68df..008f80c57 100644
--- a/packages/taler-wallet-webextension/src/wxBackend.ts
+++ b/packages/taler-wallet-webextension/src/wxBackend.ts
@@ -275,7 +275,7 @@ async function dispatch<
 
 async function reinitWallet(): Promise<void> {
   if (currentWallet) {
-    currentWallet.stop();
+    await currentWallet.client.call(WalletApiOperation.Shutdown, {});
     currentWallet = undefined;
   }
   currentDatabase = undefined;

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