gnunet-svn
[Top][All Lists]
Advanced

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

[taler-wallet-core] branch master updated: taler-harness: add exchange-p


From: gnunet
Subject: [taler-wallet-core] branch master updated: taler-harness: add exchange-purse test
Date: Tue, 29 Aug 2023 09:47:01 +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 55bdc161b taler-harness: add exchange-purse test
55bdc161b is described below

commit 55bdc161b58ddf4f24e32dff9acd8011a4364327
Author: Florian Dold <florian@dold.me>
AuthorDate: Tue Aug 29 09:45:45 2023 +0200

    taler-harness: add exchange-purse test
---
 .../src/integrationtests/test-exchange-purse.ts    | 224 +++++++++++++++++++++
 .../src/integrationtests/testrunner.ts             |   9 +-
 packages/taler-util/src/payto.ts                   |  22 ++
 packages/taler-util/src/taler-crypto.ts            |   5 +-
 packages/taler-wallet-core/src/index.ts            |   8 +-
 .../src/operations/pay-peer-common.ts              |  22 --
 .../src/operations/pay-peer-pull-credit.ts         |   2 +-
 .../src/operations/pay-peer-push-credit.ts         |   2 +-
 8 files changed, 261 insertions(+), 33 deletions(-)

diff --git a/packages/taler-harness/src/integrationtests/test-exchange-purse.ts 
b/packages/taler-harness/src/integrationtests/test-exchange-purse.ts
new file mode 100644
index 000000000..5a1d02692
--- /dev/null
+++ b/packages/taler-harness/src/integrationtests/test-exchange-purse.ts
@@ -0,0 +1,224 @@
+/*
+ This file is part of GNU Taler
+ (C) 2023 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 {
+  AbsoluteTime,
+  ContractTermsUtil,
+  decodeCrock,
+  Duration,
+  encodeCrock,
+  getRandomBytes,
+  hash,
+  j2s,
+  PeerContractTerms,
+  TalerError,
+  TalerPreciseTimestamp,
+} from "@gnu-taler/taler-util";
+import {
+  checkReserve,
+  CryptoDispatcher,
+  downloadExchangeInfo,
+  EncryptContractRequest,
+  findDenomOrThrow,
+  SpendCoinDetails,
+  SynchronousCryptoWorkerFactoryPlain,
+  topupReserveWithDemobank,
+  Wallet,
+  withdrawCoin,
+} from "@gnu-taler/taler-wallet-core";
+import { GlobalTestState, harnessHttpLib } from "../harness/harness.js";
+import { createSimpleTestkudosEnvironmentV2 } from "../harness/helpers.js";
+
+/**
+ * Test the exchange's purse API.
+ */
+export async function runExchangePurseTest(t: GlobalTestState) {
+  // Set up test environment
+
+  const { bank, exchange } = await createSimpleTestkudosEnvironmentV2(t);
+
+  const http = harnessHttpLib;
+  const cryptoDisp = new CryptoDispatcher(
+    new SynchronousCryptoWorkerFactoryPlain(),
+  );
+  const cryptoApi = cryptoDisp.cryptoApi;
+
+  try {
+    // Withdraw digital cash into the wallet.
+
+    const exchangeInfo = await downloadExchangeInfo(exchange.baseUrl, http);
+
+    const reserveKeyPair = await cryptoApi.createEddsaKeypair({});
+
+    let reserveUrl = new URL(
+      `reserves/${reserveKeyPair.pub}`,
+      exchange.baseUrl,
+    );
+    reserveUrl.searchParams.set("timeout_ms", "30000");
+    const longpollReq = http.fetch(reserveUrl.href, {
+      method: "GET",
+    });
+
+    await topupReserveWithDemobank({
+      amount: "TESTKUDOS:10",
+      http,
+      reservePub: reserveKeyPair.pub,
+      bankAccessApiBaseUrl: bank.bankAccessApiBaseUrl,
+      exchangeInfo,
+    });
+
+    console.log("waiting for longpoll request");
+    const resp = await longpollReq;
+    console.log(`got response, status ${resp.status}`);
+
+    console.log(exchangeInfo);
+
+    await checkReserve(http, exchange.baseUrl, reserveKeyPair.pub);
+
+    const d1 = findDenomOrThrow(exchangeInfo, "TESTKUDOS:8", {
+      denomselAllowLate: Wallet.defaultConfig.testing.denomselAllowLate,
+    });
+
+    const coin = await withdrawCoin({
+      http,
+      cryptoApi,
+      reserveKeyPair: {
+        reservePriv: reserveKeyPair.priv,
+        reservePub: reserveKeyPair.pub,
+      },
+      denom: d1,
+      exchangeBaseUrl: exchange.baseUrl,
+    });
+
+    const amount = "TESTKUDOS:5";
+    const purseFee = "TESTKUDOS:0";
+
+    const mergeTimestamp = TalerPreciseTimestamp.now();
+
+    const contractTerms: PeerContractTerms = {
+      amount,
+      summary: "Hello",
+      purse_expiration: AbsoluteTime.toProtocolTimestamp(
+        AbsoluteTime.addDuration(
+          AbsoluteTime.now(),
+          Duration.fromSpec({ minutes: 1 }),
+        ),
+      ),
+    };
+
+    const mergeReservePair = await cryptoApi.createEddsaKeypair({});
+    const pursePair = await cryptoApi.createEddsaKeypair({});
+    const mergePair = await cryptoApi.createEddsaKeypair({});
+    const contractPair = await cryptoApi.createEddsaKeypair({});
+    const contractEncNonce = encodeCrock(getRandomBytes(24));
+
+    const pursePub = pursePair.pub;
+
+    const hContractTerms = ContractTermsUtil.hashContractTerms(contractTerms);
+
+    const purseSigResp = await cryptoApi.signPurseCreation({
+      hContractTerms,
+      mergePub: mergePair.pub,
+      minAge: 0,
+      purseAmount: amount,
+      purseExpiration: contractTerms.purse_expiration,
+      pursePriv: pursePair.priv,
+    });
+
+    const coinSpend: SpendCoinDetails = {
+      ageCommitmentProof: undefined,
+      coinPriv: coin.coinPriv,
+      coinPub: coin.coinPub,
+      contribution: amount,
+      denomPubHash: coin.denomPubHash,
+      denomSig: coin.denomSig,
+    };
+
+    const depositSigsResp = await cryptoApi.signPurseDeposits({
+      exchangeBaseUrl: exchange.baseUrl,
+      pursePub: pursePair.pub,
+      coins: [coinSpend],
+    });
+
+    const encryptContractRequest: EncryptContractRequest = {
+      contractTerms: contractTerms,
+      mergePriv: mergePair.priv,
+      pursePriv: pursePair.priv,
+      pursePub: pursePair.pub,
+      contractPriv: contractPair.priv,
+      contractPub: contractPair.pub,
+      nonce: contractEncNonce,
+    };
+
+    const econtractResp = await cryptoApi.encryptContractForMerge(
+      encryptContractRequest,
+    );
+
+    const econtractHash = encodeCrock(
+      hash(decodeCrock(econtractResp.econtract.econtract)),
+    );
+
+    const createPurseUrl = new URL(
+      `purses/${pursePair.pub}/create`,
+      exchange.baseUrl,
+    );
+
+    const reqBody = {
+      amount: amount,
+      merge_pub: mergePair.pub,
+      purse_sig: purseSigResp.sig,
+      h_contract_terms: hContractTerms,
+      purse_expiration: contractTerms.purse_expiration,
+      deposits: depositSigsResp.deposits,
+      min_age: 0,
+      econtract: econtractResp.econtract,
+    };
+
+    const httpResp = await http.fetch(createPurseUrl.href, {
+      method: "POST",
+      body: reqBody,
+    });
+
+    const respBody = await httpResp.json();
+
+    console.log("status", httpResp.status);
+
+    console.log(j2s(respBody));
+
+    const mergeUrl = new URL(`purses/${pursePub}/merge`, exchange.baseUrl);
+    mergeUrl.searchParams.set("timeout_ms", "300");
+    const statusResp = await http.fetch(mergeUrl.href, {});
+
+    const statusRespBody = await statusResp.json();
+
+    console.log(j2s(statusRespBody));
+
+    t.assertTrue(statusRespBody.merge_timestamp === undefined);
+  } catch (e) {
+    if (e instanceof TalerError) {
+      console.log(e);
+      console.log(j2s(e.errorDetail));
+    } else {
+      console.log(e);
+    }
+    throw e;
+  }
+}
+
+runExchangePurseTest.suites = ["wallet"];
diff --git a/packages/taler-harness/src/integrationtests/testrunner.ts 
b/packages/taler-harness/src/integrationtests/testrunner.ts
index cbdca04b9..226fd6b09 100644
--- a/packages/taler-harness/src/integrationtests/testrunner.ts
+++ b/packages/taler-harness/src/integrationtests/testrunner.ts
@@ -14,7 +14,12 @@
  GNU Taler; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
  */
 
-import { CancellationToken, Logger, minimatch, setGlobalLogLevelFromString } 
from "@gnu-taler/taler-util";
+import {
+  CancellationToken,
+  Logger,
+  minimatch,
+  setGlobalLogLevelFromString,
+} from "@gnu-taler/taler-util";
 import * as child_process from "child_process";
 import * as fs from "fs";
 import * as os from "os";
@@ -105,6 +110,7 @@ import { runPeerRepairTest } from "./test-peer-repair.js";
 import { runPaymentShareTest } from "./test-payment-share.js";
 import { runSimplePaymentTest } from "./test-simple-payment.js";
 import { runTermOfServiceFormatTest } from "./test-tos-format.js";
+import { runExchangePurseTest } from "./test-exchange-purse.js";
 
 /**
  * Test runner.
@@ -137,6 +143,7 @@ const allTests: TestMainFunction[] = [
   runFeeRegressionTest,
   runForcedSelectionTest,
   runKycTest,
+  runExchangePurseTest,
   runExchangeDepositTest,
   runLibeufinAnastasisFacadeTest,
   runLibeufinApiBankaccountTest,
diff --git a/packages/taler-util/src/payto.ts b/packages/taler-util/src/payto.ts
index dd35b44be..2b0af4cc2 100644
--- a/packages/taler-util/src/payto.ts
+++ b/packages/taler-util/src/payto.ts
@@ -239,3 +239,25 @@ export function parsePaytoUri(s: string): PaytoUri | 
undefined {
     isKnown: false,
   };
 }
+
+export function talerPaytoFromExchangeReserve(
+  exchangeBaseUrl: string,
+  reservePub: string,
+): string {
+  const url = new URL(exchangeBaseUrl);
+  let proto: string;
+  if (url.protocol === "http:") {
+    proto = "taler-reserve-http";
+  } else if (url.protocol === "https:") {
+    proto = "taler-reserve";
+  } else {
+    throw Error(`unsupported exchange base URL protocol (${url.protocol})`);
+  }
+
+  let path = url.pathname;
+  if (!path.endsWith("/")) {
+    path = path + "/";
+  }
+
+  return `payto://${proto}/${url.host}${url.pathname}${reservePub}`;
+}
diff --git a/packages/taler-util/src/taler-crypto.ts 
b/packages/taler-util/src/taler-crypto.ts
index d52edc1e5..9425a9320 100644
--- a/packages/taler-util/src/taler-crypto.ts
+++ b/packages/taler-util/src/taler-crypto.ts
@@ -1004,7 +1004,7 @@ export enum TalerSignaturePurpose {
   SYNC_BACKUP_UPLOAD = 1450,
 }
 
-export const enum WalletAccountMergeFlags {
+export enum WalletAccountMergeFlags {
   /**
    * Not a legal mode!
    */
@@ -1281,7 +1281,8 @@ export namespace AgeRestriction {
   }
 
   const PublishedAgeRestrictionBaseKey: Edx25519PublicKey = decodeCrock(
-    "CH0VKFDZ2GWRWHQBBGEK9MWV5YDQVJ0RXEE0KYT3NMB69F0R96TG");
+    "CH0VKFDZ2GWRWHQBBGEK9MWV5YDQVJ0RXEE0KYT3NMB69F0R96TG",
+  );
 
   export async function restrictionCommitSeeded(
     ageMask: number,
diff --git a/packages/taler-wallet-core/src/index.ts 
b/packages/taler-wallet-core/src/index.ts
index 8dd06fe2b..d64f7d5e6 100644
--- a/packages/taler-wallet-core/src/index.ts
+++ b/packages/taler-wallet-core/src/index.ts
@@ -51,12 +51,8 @@ export * from "./operations/refresh.js";
 
 export * from "./dbless.js";
 
-export {
-  nativeCryptoR,
-  nativeCrypto,
-  nullCrypto,
-  TalerCryptoInterface,
-} from "./crypto/cryptoImplementation.js";
+export * from "./crypto/cryptoTypes.js";
+export * from "./crypto/cryptoImplementation.js";
 
 export * from "./util/timer.js";
 export * from "./util/denominations.js";
diff --git a/packages/taler-wallet-core/src/operations/pay-peer-common.ts 
b/packages/taler-wallet-core/src/operations/pay-peer-common.ts
index 1bc2e8d49..4fdfecb4d 100644
--- a/packages/taler-wallet-core/src/operations/pay-peer-common.ts
+++ b/packages/taler-wallet-core/src/operations/pay-peer-common.ts
@@ -420,28 +420,6 @@ export const codecForExchangePurseStatus = (): 
Codec<ExchangePurseStatus> =>
     .property("merge_timestamp", codecOptional(codecForTimestamp))
     .build("ExchangePurseStatus");
 
-export function talerPaytoFromExchangeReserve(
-  exchangeBaseUrl: string,
-  reservePub: string,
-): string {
-  const url = new URL(exchangeBaseUrl);
-  let proto: string;
-  if (url.protocol === "http:") {
-    proto = "taler-reserve-http";
-  } else if (url.protocol === "https:") {
-    proto = "taler-reserve";
-  } else {
-    throw Error(`unsupported exchange base URL protocol (${url.protocol})`);
-  }
-
-  let path = url.pathname;
-  if (!path.endsWith("/")) {
-    path = path + "/";
-  }
-
-  return `payto://${proto}/${url.host}${url.pathname}${reservePub}`;
-}
-
 export async function getMergeReserveInfo(
   ws: InternalWalletState,
   req: {
diff --git a/packages/taler-wallet-core/src/operations/pay-peer-pull-credit.ts 
b/packages/taler-wallet-core/src/operations/pay-peer-pull-credit.ts
index 88b441cdd..954300264 100644
--- a/packages/taler-wallet-core/src/operations/pay-peer-pull-credit.ts
+++ b/packages/taler-wallet-core/src/operations/pay-peer-pull-credit.ts
@@ -45,6 +45,7 @@ import {
   j2s,
   makeErrorDetail,
   stringifyTalerUri,
+  talerPaytoFromExchangeReserve,
 } from "@gnu-taler/taler-util";
 import {
   readSuccessResponseJsonOrErrorCode,
@@ -74,7 +75,6 @@ import {
 import {
   codecForExchangePurseStatus,
   getMergeReserveInfo,
-  talerPaytoFromExchangeReserve,
 } from "./pay-peer-common.js";
 import {
   constructTransactionIdentifier,
diff --git a/packages/taler-wallet-core/src/operations/pay-peer-push-credit.ts 
b/packages/taler-wallet-core/src/operations/pay-peer-push-credit.ts
index e76b934fa..c552d63f0 100644
--- a/packages/taler-wallet-core/src/operations/pay-peer-push-credit.ts
+++ b/packages/taler-wallet-core/src/operations/pay-peer-push-credit.ts
@@ -47,6 +47,7 @@ import {
   j2s,
   makeErrorDetail,
   parsePayPushUri,
+  talerPaytoFromExchangeReserve,
 } from "@gnu-taler/taler-util";
 import { readSuccessResponseJsonOrThrow } from "@gnu-taler/taler-util/http";
 import {
@@ -71,7 +72,6 @@ import { updateExchangeFromUrl } from "./exchanges.js";
 import {
   codecForExchangePurseStatus,
   getMergeReserveInfo,
-  talerPaytoFromExchangeReserve,
 } from "./pay-peer-common.js";
 import {
   TransitionInfo,

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