summaryrefslogtreecommitdiff
path: root/src/crypto
diff options
context:
space:
mode:
authorFlorian Dold <florian.dold@gmail.com>2019-07-31 01:33:56 +0200
committerFlorian Dold <florian.dold@gmail.com>2019-07-31 01:33:56 +0200
commitcc4e8ddc85d36f29a7385a7f4eb08c77f46b3af6 (patch)
tree56b7d5a083c5b64a72d0905ad04616b97986538e /src/crypto
parentbcefbd7aab5f33f93d626c6421a1a1218c1a91a2 (diff)
downloadwallet-core-cc4e8ddc85d36f29a7385a7f4eb08c77f46b3af6.tar.gz
wallet-core-cc4e8ddc85d36f29a7385a7f4eb08c77f46b3af6.tar.bz2
wallet-core-cc4e8ddc85d36f29a7385a7f4eb08c77f46b3af6.zip
headless wallet WIP
Diffstat (limited to 'src/crypto')
-rw-r--r--src/crypto/cryptoApi-test.ts24
-rw-r--r--src/crypto/cryptoApi.ts29
-rw-r--r--src/crypto/cryptoWorker.ts21
-rw-r--r--src/crypto/emscInterface-test.ts8
-rw-r--r--src/crypto/emscInterface.ts3
-rw-r--r--src/crypto/emscLoader.js36
6 files changed, 94 insertions, 27 deletions
diff --git a/src/crypto/cryptoApi-test.ts b/src/crypto/cryptoApi-test.ts
index 24342a436..6d43e2e6e 100644
--- a/src/crypto/cryptoApi-test.ts
+++ b/src/crypto/cryptoApi-test.ts
@@ -26,10 +26,12 @@ import {
import { CryptoApi } from "./cryptoApi";
-const masterPub1: string = "CQQZ9DY3MZ1ARMN5K1VKDETS04Y2QCKMMCFHZSWJWWVN82BTTH00";
+const masterPub1: string =
+ "CQQZ9DY3MZ1ARMN5K1VKDETS04Y2QCKMMCFHZSWJWWVN82BTTH00";
const denomValid1: DenominationRecord = {
- denomPub: "51R7ARKCD5HJTTV5F4G0M818E9SP280A40G2GVH04CR30GHS84R3JHHP6GSM2D9Q6514CGT568R32C9J6CWM4DSH64TM4DSM851K0CA48CVKAC1P6H144C2160T46DHK8CVM4HJ274S38C1M6S338D9N6GWM8DT684T3JCT36S13EC9G88R3EGHQ8S0KJGSQ60SKGD216N33AGJ2651K2E9S60TMCD1N75244HHQ6X33EDJ570R3GGJ2651MACA38D130DA560VK4HHJ68WK2CA26GW3ECSH6D13EC9S88VK2GT66WVK8D9G750K0D9R8RRK4DHQ71332GHK8D23GE26710M2H9K6WVK8HJ38MVKEGA66N23AC9H88VKACT58MV3CCSJ6H1K4DT38GRK0C9M8N33CE1R60V4AHA38H1KECSH6S33JH9N8GRKGH1K68S36GH354520818CMG26C1H60R30C935452081918G2J2G0",
+ denomPub:
+ "51R7ARKCD5HJTTV5F4G0M818E9SP280A40G2GVH04CR30GHS84R3JHHP6GSM2D9Q6514CGT568R32C9J6CWM4DSH64TM4DSM851K0CA48CVKAC1P6H144C2160T46DHK8CVM4HJ274S38C1M6S338D9N6GWM8DT684T3JCT36S13EC9G88R3EGHQ8S0KJGSQ60SKGD216N33AGJ2651K2E9S60TMCD1N75244HHQ6X33EDJ570R3GGJ2651MACA38D130DA560VK4HHJ68WK2CA26GW3ECSH6D13EC9S88VK2GT66WVK8D9G750K0D9R8RRK4DHQ71332GHK8D23GE26710M2H9K6WVK8HJ38MVKEGA66N23AC9H88VKACT58MV3CCSJ6H1K4DT38GRK0C9M8N33CE1R60V4AHA38H1KECSH6S33JH9N8GRKGH1K68S36GH354520818CMG26C1H60R30C935452081918G2J2G0",
denomPubHash: "dummy",
exchangeBaseUrl: "https://exchange.example.com/",
feeDeposit: {
@@ -53,7 +55,8 @@ const denomValid1: DenominationRecord = {
value: 0,
},
isOffered: true,
- masterSig: "CJFJCQ48Q45PSGJ5KY94N6M2TPARESM2E15BSPBD95YVVPEARAEQ6V6G4Z2XBMS0QM0F3Y9EYVP276FCS90EQ1578ZC8JHFBZ3NGP3G",
+ masterSig:
+ "CJFJCQ48Q45PSGJ5KY94N6M2TPARESM2E15BSPBD95YVVPEARAEQ6V6G4Z2XBMS0QM0F3Y9EYVP276FCS90EQ1578ZC8JHFBZ3NGP3G",
stampExpireDeposit: "/Date(1851580381)/",
stampExpireLegal: "/Date(1567756381)/",
stampExpireWithdraw: "/Date(2482300381)/",
@@ -69,24 +72,25 @@ const denomValid1: DenominationRecord = {
const denomInvalid1 = JSON.parse(JSON.stringify(denomValid1));
denomInvalid1.value.value += 1;
-test("string hashing", async (t) => {
+test("string hashing", async t => {
const crypto = new CryptoApi();
const s = await crypto.hashString("hello taler");
- const sh = "8RDMADB3YNF3QZBS3V467YZVJAMC2QAQX0TZGVZ6Q5PFRRAJFT70HHN0QF661QR9QWKYMMC7YEMPD679D2RADXCYK8Y669A2A5MKQFR";
+ const sh =
+ "8RDMADB3YNF3QZBS3V467YZVJAMC2QAQX0TZGVZ6Q5PFRRAJFT70HHN0QF661QR9QWKYMMC7YEMPD679D2RADXCYK8Y669A2A5MKQFR";
t.true(s === sh);
t.pass();
});
-test("precoin creation", async (t) => {
+test("precoin creation", async t => {
const crypto = new CryptoApi();
- const {priv, pub} = await crypto.createEddsaKeypair();
+ const { priv, pub } = await crypto.createEddsaKeypair();
const r: ReserveRecord = {
created: 0,
current_amount: null,
exchange_base_url: "https://example.com/exchange",
hasPayback: false,
- precoin_amount: {currency: "PUDOS", value: 0, fraction: 0},
- requested_amount: {currency: "PUDOS", value: 0, fraction: 0},
+ precoin_amount: { currency: "PUDOS", value: 0, fraction: 0 },
+ requested_amount: { currency: "PUDOS", value: 0, fraction: 0 },
reserve_priv: priv,
reserve_pub: pub,
timestamp_confirmed: 0,
@@ -98,7 +102,7 @@ test("precoin creation", async (t) => {
t.pass();
});
-test("denom validation", async (t) => {
+test("denom validation", async t => {
const crypto = new CryptoApi();
let v: boolean;
v = await crypto.isValidDenom(denomValid1, masterPub1);
diff --git a/src/crypto/cryptoApi.ts b/src/crypto/cryptoApi.ts
index 43a3bc228..d3a93ff8d 100644
--- a/src/crypto/cryptoApi.ts
+++ b/src/crypto/cryptoApi.ts
@@ -98,6 +98,28 @@ export class CryptoApi {
*/
private numBusy: number = 0;
+ public enableTracing = false;
+
+ /**
+ * Terminate all worker threads.
+ */
+ terminateWorkers() {
+ for (let worker of this.workers) {
+ if (worker.w) {
+ worker.w.terminate();
+ if (worker.terminationTimerHandle) {
+ worker.terminationTimerHandle.clear();
+ worker.terminationTimerHandle = null;
+ }
+ if (worker.currentWorkItem) {
+ worker.currentWorkItem.reject(Error("explicitly terminated"));
+ worker.currentWorkItem = null;
+ }
+ worker.w = null;
+ }
+ }
+ }
+
/**
* Start a worker (if not started) and set as busy.
*/
@@ -136,7 +158,7 @@ export class CryptoApi {
ws.w = null;
}
};
- ws.terminationTimerHandle = timer.after(20 * 1000, destroy);
+ ws.terminationTimerHandle = timer.after(5 * 1000, destroy);
}
handleWorkerError(ws: WorkerState, e: ErrorEvent) {
@@ -163,7 +185,7 @@ export class CryptoApi {
this.findWork(ws);
}
- findWork(ws: WorkerState) {
+ private findWork(ws: WorkerState) {
// try to find more work for this worker
for (let i = 0; i < NUM_PRIO; i++) {
const q = this.workQueues[NUM_PRIO - i - 1];
@@ -193,7 +215,8 @@ export class CryptoApi {
console.error(`RPC with id ${id} has no registry entry`);
return;
}
- console.log(
+
+ this.enableTracing && console.log(
`rpc ${currentWorkItem.operation} took ${timer.performanceNow() -
currentWorkItem.startTime}ms`,
);
diff --git a/src/crypto/cryptoWorker.ts b/src/crypto/cryptoWorker.ts
index 9c5263a6f..5acda9053 100644
--- a/src/crypto/cryptoWorker.ts
+++ b/src/crypto/cryptoWorker.ts
@@ -56,6 +56,9 @@ import {
import * as native from "./emscInterface";
namespace RpcFunctions {
+
+ export let enableTracing: boolean = false;
+
/**
* Create a pre-coin of the given denomination to be withdrawn from then given
* reserve.
@@ -735,19 +738,25 @@ worker.onmessage = (msg: MessageEvent) => {
return;
}
- console.log("onmessage with", msg.data.operation);
- console.log("foo");
+ if (RpcFunctions.enableTracing) {
+ console.log("onmessage with", msg.data.operation);
+ }
emscLoader.getLib().then(p => {
const lib = p.lib;
if (!native.isInitialized()) {
- console.log("initializing emscripten for then first time with lib");
+ if (RpcFunctions.enableTracing) {
+ console.log("initializing emscripten for then first time with lib");
+ }
native.initialize(lib);
}
-
- console.log("about to execute", msg.data.operation);
+ if (RpcFunctions.enableTracing) {
+ console.log("about to execute", msg.data.operation);
+ }
const res = f(...msg.data.args);
- console.log("finished executing", msg.data.operation);
+ if (RpcFunctions.enableTracing) {
+ console.log("finished executing", msg.data.operation);
+ }
worker.postMessage({ result: res, id: msg.data.id });
});
};
diff --git a/src/crypto/emscInterface-test.ts b/src/crypto/emscInterface-test.ts
index 58d83e6fe..305e50ff4 100644
--- a/src/crypto/emscInterface-test.ts
+++ b/src/crypto/emscInterface-test.ts
@@ -17,8 +17,14 @@
// tslint:disable:max-line-length
import test from "ava";
+import * as emscLoader from "./emscLoader";
import * as native from "./emscInterface";
+test.before(async () => {
+ const { lib } = await emscLoader.getLib();
+ native.initialize(lib);
+});
+
test("string hashing", (t) => {
const x = native.ByteArray.fromStringWithNull("hello taler");
const h = "8RDMADB3YNF3QZBS3V467YZVJAMC2QAQX0TZGVZ6Q5PFRRAJFT70HHN0QF661QR9QWKYMMC7YEMPD679D2RADXCYK8Y669A2A5MKQFR";
@@ -99,7 +105,7 @@ test("withdraw-request", (t) => {
});
-test("withdraw-request", (t) => {
+test("currency-conversion", (t) => {
const a1 = new native.Amount({currency: "KUDOS", value: 1, fraction: 50000000});
const a2 = new native.Amount({currency: "KUDOS", value: 1, fraction: 50000000});
a1.add(a2);
diff --git a/src/crypto/emscInterface.ts b/src/crypto/emscInterface.ts
index 2ddc15a37..70a85cda1 100644
--- a/src/crypto/emscInterface.ts
+++ b/src/crypto/emscInterface.ts
@@ -43,6 +43,9 @@ export function initialize(lib: EmscLib) {
if (!lib) {
throw Error("library must be object");
}
+ if (!lib.ccall) {
+ throw Error("sanity check failed: EmscLib does not have 'ccall'");
+ }
if (maybeEmscEnv) {
throw Error("emsc lib already initialized");
}
diff --git a/src/crypto/emscLoader.js b/src/crypto/emscLoader.js
index 59437da42..25dc6b85c 100644
--- a/src/crypto/emscLoader.js
+++ b/src/crypto/emscLoader.js
@@ -25,20 +25,29 @@
*/
let cachedLib = undefined;
+let cachedLibPromise = undefined;
+
+export let enableTracing = false;
/**
* Load the taler emscripten lib.
*
* If in a WebWorker, importScripts is used. Inside a browser, the module must
* be globally available. Inside node, require is used.
+ *
+ * Returns a Promise<{ lib: EmscLib }>
*/
export function getLib() {
- console.log("in getLib");
+ enableTracing && console.log("in getLib");
if (cachedLib) {
- console.log("lib is cached");
+ enableTracing && console.log("lib is cached");
return Promise.resolve({ lib: cachedLib });
}
+ if (cachedLibPromise) {
+ return cachedLibPromise;
+ }
if (typeof require !== "undefined") {
+ enableTracing && console.log("trying to load emscripten lib with 'require'");
// Make sure that TypeScript doesn't try
// to check the taler-emscripten-lib.
const indirectRequire = require;
@@ -49,17 +58,30 @@ export function getLib() {
const savedImportScripts = g.importScripts;
delete g.importScripts;
// Assume that the code is run from the build/ directory.
- const lib = indirectRequire("../../../emscripten/taler-emscripten-lib.js");
+ const libFn = indirectRequire("../../../emscripten/taler-emscripten-lib.js");
+ const lib = libFn();
g.importScripts = savedImportScripts;
if (lib) {
- cachedLib = lib;
- return Promise.resolve({ lib: cachedLib });
+ if (!lib.ccall) {
+ throw Error("sanity check failed: taler-emscripten lib does not have 'ccall'");
+ }
+ cachedLibPromise = new Promise((resolve, reject) => {
+ lib.onRuntimeInitialized = () => {
+ cachedLib = lib;
+ cachedLibPromise = undefined;
+ resolve({ lib: cachedLib });
+ };
+ });
+ return cachedLibPromise;
+ } else {
+ // When we're running as a webpack bundle, the above require might
+ // have failed and returned 'undefined', so we try other ways to import.
+ console.log("failed to load emscripten lib with 'require', trying alternatives");
}
- // When we're running as a webpack bundle, the above require might
- // have failed and returned 'undefined', so we try other ways to import.
}
if (typeof importScripts !== "undefined") {
+ console.log("trying to load emscripten lib with 'importScripts'");
self.TalerEmscriptenLib = {};
importScripts('/emscripten/taler-emscripten-lib.js')
if (!self.TalerEmscriptenLib) {