refactor work queue

This commit is contained in:
Florian Dold 2016-10-13 20:02:42 +02:00
parent d3b49c0a2f
commit 0b198e0888
7 changed files with 222 additions and 214 deletions

View File

@ -28,11 +28,6 @@ import {CoinWithDenom} from "./wallet";
import {PayCoinInfo} from "./types"; import {PayCoinInfo} from "./types";
import {RefreshSession} from "./types"; import {RefreshSession} from "./types";
interface RegistryEntry {
resolve: any;
reject: any;
workerIndex: number;
}
interface WorkerState { interface WorkerState {
/** /**
@ -41,19 +36,14 @@ interface WorkerState {
w: Worker|null; w: Worker|null;
/** /**
* Are we currently running a task on this worker? * Work we're currently executing or null if not busy.
*/ */
busy: boolean; currentWorkItem: WorkItem|null;
/** /**
* Timer to terminate the worker if it's not busy enough. * Timer to terminate the worker if it's not busy enough.
*/ */
terminationTimerHandle: number|null; terminationTimerHandle: number|null;
/**
* Index of this worker in the list of workers.
*/
workerIndex: number;
} }
interface WorkItem { interface WorkItem {
@ -61,6 +51,11 @@ interface WorkItem {
args: any[]; args: any[];
resolve: any; resolve: any;
reject: any; reject: any;
/**
* Serial id to identify a matching response.
*/
rpcId: number;
} }
@ -72,27 +67,21 @@ const NUM_PRIO = 5;
export class CryptoApi { export class CryptoApi {
private nextRpcId: number = 1; private nextRpcId: number = 1;
private rpcRegistry: {[n: number]: RegistryEntry} = {};
private workers: WorkerState[]; private workers: WorkerState[];
private workQueues: WorkItem[][]; private workQueues: WorkItem[][];
/** /**
* Number of busy workers. * Number of busy workers.
*/ */
private numBusy: number = 0; private numBusy: number = 0;
/**
* Number if pending work items.
*/
private numWaiting: number = 0;
/** /**
* Start a worker (if not started) and set as busy. * Start a worker (if not started) and set as busy.
*/ */
wake(ws: WorkerState) { wake<T>(ws: WorkerState, work: WorkItem): void {
if (ws.busy) { if (ws.currentWorkItem != null) {
throw Error("assertion failed"); throw Error("assertion failed");
} }
ws.busy = true; ws.currentWorkItem = work;
this.numBusy++; this.numBusy++;
if (!ws.w) { if (!ws.w) {
let w = new Worker("/lib/wallet/cryptoWorker.js"); let w = new Worker("/lib/wallet/cryptoWorker.js");
@ -100,27 +89,45 @@ export class CryptoApi {
w.onerror = (e: ErrorEvent) => this.handleWorkerError(ws, e); w.onerror = (e: ErrorEvent) => this.handleWorkerError(ws, e);
ws.w = w; ws.w = w;
} }
let msg: any = {
operation: work.operation, args: work.args,
id: work.rpcId
};
this.resetWorkerTimeout(ws);
ws.w!.postMessage(msg);
}
resetWorkerTimeout(ws: WorkerState) {
if (ws.terminationTimerHandle != null) { if (ws.terminationTimerHandle != null) {
clearTimeout(ws.terminationTimerHandle); clearTimeout(ws.terminationTimerHandle);
} }
let destroy = () => { let destroy = () => {
if (ws.w && !ws.busy) { // terminate worker if it's idle
if (ws.w && ws.currentWorkItem == null) {
ws.w!.terminate(); ws.w!.terminate();
ws.w = null; ws.w = null;
} }
} };
ws.terminationTimerHandle = setTimeout(destroy, 20 * 1000); ws.terminationTimerHandle = setTimeout(destroy, 20 * 1000);
} }
handleWorkerError(ws: WorkerState, e: ErrorEvent) { handleWorkerError(ws: WorkerState, e: ErrorEvent) {
console.error("error in worker", e); if (ws.currentWorkItem) {
console.error(`error in worker during ${ws.currentWorkItem!.operation}`, e);
} else {
console.error("error in worker", e);
}
console.error(e.message);
try { try {
ws.w!.terminate(); ws.w!.terminate();
ws.w = null;
} catch (e) { } catch (e) {
console.error(e); console.error(e);
} }
if (ws.busy) { if (ws.currentWorkItem != null) {
ws.busy = false; ws.currentWorkItem.reject(e);
ws.currentWorkItem = null;
this.numBusy--; this.numBusy--;
} }
this.findWork(ws); this.findWork(ws);
@ -132,14 +139,7 @@ export class CryptoApi {
let q = this.workQueues[NUM_PRIO - i - 1]; let q = this.workQueues[NUM_PRIO - i - 1];
if (q.length != 0) { if (q.length != 0) {
let work: WorkItem = q.shift()!; let work: WorkItem = q.shift()!;
let msg: any = { this.wake(ws, work);
operation: work.operation,
args: work.args,
id: this.registerRpcId(work.resolve, work.reject, ws.workerIndex),
};
this.wake(ws);
ws.w!.postMessage(msg);
return; return;
} }
} }
@ -151,22 +151,19 @@ export class CryptoApi {
console.error("rpc id must be number"); console.error("rpc id must be number");
return; return;
} }
if (!this.rpcRegistry[id]) { let currentWorkItem = ws.currentWorkItem;
ws.currentWorkItem = null;
this.numBusy--;
this.findWork(ws);
if (!currentWorkItem) {
console.error("unsolicited response from worker");
return;
}
if (id != currentWorkItem.rpcId) {
console.error(`RPC with id ${id} has no registry entry`); console.error(`RPC with id ${id} has no registry entry`);
return; return;
} }
let {resolve, workerIndex} = this.rpcRegistry[id]; currentWorkItem.resolve(msg.data.result);
delete this.rpcRegistry[id];
if (workerIndex != ws.workerIndex) {
throw Error("assertion failed");
}
if (!ws.busy) {
throw Error("assertion failed");
}
ws.busy = false;
this.numBusy--;
resolve(msg.data.result);
this.findWork(ws);
} }
constructor() { constructor() {
@ -175,9 +172,8 @@ export class CryptoApi {
for (let i = 0; i < this.workers.length; i++) { for (let i = 0; i < this.workers.length; i++) {
this.workers[i] = { this.workers[i] = {
w: null, w: null,
busy: false,
terminationTimerHandle: null, terminationTimerHandle: null,
workerIndex: i, currentWorkItem: null,
}; };
} }
this.workQueues = []; this.workQueues = [];
@ -186,45 +182,34 @@ export class CryptoApi {
} }
} }
private registerRpcId(resolve: any, reject: any,
workerIndex: number): number {
let id = this.nextRpcId++;
this.rpcRegistry[id] = {resolve, reject, workerIndex};
return id;
}
private doRpc<T>(operation: string, priority: number, private doRpc<T>(operation: string, priority: number,
...args: any[]): Promise<T> { ...args: any[]): Promise<T> {
if (this.numBusy == this.workers.length) {
let q = this.workQueues[priority];
if (!q) {
throw Error("assertion failed");
}
return new Promise<T>((resolve, reject) => {
this.workQueues[priority].push({operation, args, resolve, reject});
});
}
for (let i = 0; i < this.workers.length; i++) { return new Promise((resolve, reject) => {
let ws = this.workers[i]; let rpcId = this.nextRpcId++;
if (ws.busy) { let workItem: WorkItem = {operation, args, resolve, reject, rpcId};
continue;
if (this.numBusy == this.workers.length) {
let q = this.workQueues[priority];
if (!q) {
throw Error("assertion failed");
}
this.workQueues[priority].push(workItem);
return;
} }
this.wake(ws); for (let i = 0; i < this.workers.length; i++) {
let ws = this.workers[i];
if (ws.currentWorkItem != null) {
continue;
}
return new Promise<T>((resolve, reject) => { this.wake<T>(ws, workItem);
let msg: any = { return;
operation, args, }
id: this.registerRpcId(resolve, reject, i),
};
ws.w!.postMessage(msg);
});
}
throw Error("assertion failed"); throw Error("assertion failed");
});
} }
@ -270,4 +255,4 @@ export class CryptoApi {
meltAmount, meltAmount,
meltFee); meltFee);
} }
} }

View File

@ -79,9 +79,13 @@ namespace RpcFunctions {
let coinPub = coinPriv.getPublicKey(); let coinPub = coinPriv.getPublicKey();
let blindingFactor = native.RsaBlindingKeySecret.create(); let blindingFactor = native.RsaBlindingKeySecret.create();
let pubHash: native.HashCode = coinPub.hash(); let pubHash: native.HashCode = coinPub.hash();
let ev: native.ByteArray = native.rsaBlind(pubHash, let ev = native.rsaBlind(pubHash,
blindingFactor, blindingFactor,
denomPub); denomPub);
if (!ev) {
throw Error("couldn't blind (malicious exchange key?)");
}
if (!denom.fee_withdraw) { if (!denom.fee_withdraw) {
throw Error("Field fee_withdraw missing"); throw Error("Field fee_withdraw missing");
@ -234,10 +238,10 @@ namespace RpcFunctions {
} }
function createWithdrawSession(kappa: number, meltCoin: Coin, export function createWithdrawSession(kappa: number, meltCoin: Coin,
newCoinDenoms: Denomination[], newCoinDenoms: Denomination[],
meltAmount: AmountJson, meltAmount: AmountJson,
meltFee: AmountJson): RefreshSession { meltFee: AmountJson): RefreshSession {
let sessionHc = new HashContext(); let sessionHc = new HashContext();
@ -268,9 +272,12 @@ namespace RpcFunctions {
let blindingFactor = native.RsaBlindingKeySecret.create(); let blindingFactor = native.RsaBlindingKeySecret.create();
let pubHash: native.HashCode = coinPub.hash(); let pubHash: native.HashCode = coinPub.hash();
let denomPub = native.RsaPublicKey.fromCrock(newCoinDenoms[i].denom_pub); let denomPub = native.RsaPublicKey.fromCrock(newCoinDenoms[i].denom_pub);
let ev: native.ByteArray = native.rsaBlind(pubHash, let ev = native.rsaBlind(pubHash,
blindingFactor, blindingFactor,
denomPub); denomPub);
if (!ev) {
throw Error("couldn't blind (malicious exchange key?)");
}
let preCoin: RefreshPreCoin = { let preCoin: RefreshPreCoin = {
blindingKey: blindingFactor.toCrock(), blindingKey: blindingFactor.toCrock(),
coinEv: ev.toCrock(), coinEv: ev.toCrock(),

View File

@ -22,7 +22,7 @@
"use strict"; "use strict";
importScripts("../emscripten/libwrapper.js", importScripts("../emscripten/taler-emscripten-lib.js",
"../vendor/system-csp-production.src.js"); "../vendor/system-csp-production.src.js");
@ -46,7 +46,7 @@ if ("object" !== typeof Module) {
{ {
let mod = System.newModule({Module: Module}); let mod = System.newModule({Module: Module});
let modName = System.normalizeSync("../emscripten/emsc"); let modName = System.normalizeSync("../emscripten/taler-emscripten-lib");
console.log("registering", modName); console.log("registering", modName);
System.set(modName, mod); System.set(modName, mod);
} }

View File

@ -14,13 +14,13 @@
TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/> TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
*/ */
import { AmountJson } from "./types"; import {AmountJson} from "./types";
import * as EmscWrapper from "../emscripten/emsc"; import * as EmscWrapper from "../emscripten/taler-emscripten-lib";
/** /**
* High-level interface to emscripten-compiled modules used * High-level interface to emscripten-compiled modules used
* by the wallet. * by the wallet.
* *
* @author Florian Dold * @author Florian Dold
*/ */
@ -43,82 +43,82 @@ let getEmsc: EmscWrapper.EmscFunGen = (...args: any[]) => Module.cwrap.apply(
var emsc = { var emsc = {
free: (ptr: number) => Module._free(ptr), free: (ptr: number) => Module._free(ptr),
get_value: getEmsc('TALER_WR_get_value', get_value: getEmsc('TALER_WR_get_value',
'number', 'number',
['number']), ['number']),
get_fraction: getEmsc('TALER_WR_get_fraction', get_fraction: getEmsc('TALER_WR_get_fraction',
'number', 'number',
['number']), ['number']),
get_currency: getEmsc('TALER_WR_get_currency', get_currency: getEmsc('TALER_WR_get_currency',
'string', 'string',
['number']), ['number']),
amount_add: getEmsc('TALER_amount_add', amount_add: getEmsc('TALER_amount_add',
'number', 'number',
['number', 'number', 'number']), ['number', 'number', 'number']),
amount_subtract: getEmsc('TALER_amount_subtract', amount_subtract: getEmsc('TALER_amount_subtract',
'number', 'number',
['number', 'number', 'number']), ['number', 'number', 'number']),
amount_normalize: getEmsc('TALER_amount_normalize', amount_normalize: getEmsc('TALER_amount_normalize',
'void', 'void',
['number']), ['number']),
amount_get_zero: getEmsc('TALER_amount_get_zero', amount_get_zero: getEmsc('TALER_amount_get_zero',
'number', 'number',
['string', 'number']), ['string', 'number']),
amount_cmp: getEmsc('TALER_amount_cmp', amount_cmp: getEmsc('TALER_amount_cmp',
'number', 'number',
['number', 'number']), ['number', 'number']),
amount_hton: getEmsc('TALER_amount_hton', amount_hton: getEmsc('TALER_amount_hton',
'void', 'void',
['number', 'number']), ['number', 'number']),
amount_ntoh: getEmsc('TALER_amount_ntoh', amount_ntoh: getEmsc('TALER_amount_ntoh',
'void', 'void',
['number', 'number']), ['number', 'number']),
hash: getEmsc('GNUNET_CRYPTO_hash', hash: getEmsc('GNUNET_CRYPTO_hash',
'void', 'void',
['number', 'number', 'number']), ['number', 'number', 'number']),
memmove: getEmsc('memmove', memmove: getEmsc('memmove',
'number', 'number',
['number', 'number', 'number']), ['number', 'number', 'number']),
rsa_public_key_free: getEmsc('GNUNET_CRYPTO_rsa_public_key_free', rsa_public_key_free: getEmsc('GNUNET_CRYPTO_rsa_public_key_free',
'void', 'void',
['number']), ['number']),
rsa_signature_free: getEmsc('GNUNET_CRYPTO_rsa_signature_free', rsa_signature_free: getEmsc('GNUNET_CRYPTO_rsa_signature_free',
'void', 'void',
['number']), ['number']),
string_to_data: getEmsc('GNUNET_STRINGS_string_to_data', string_to_data: getEmsc('GNUNET_STRINGS_string_to_data',
'number', 'number',
['number', 'number', 'number', 'number']), ['number', 'number', 'number', 'number']),
eddsa_sign: getEmsc('GNUNET_CRYPTO_eddsa_sign', eddsa_sign: getEmsc('GNUNET_CRYPTO_eddsa_sign',
'number', 'number',
['number', 'number', 'number']), ['number', 'number', 'number']),
eddsa_verify: getEmsc('GNUNET_CRYPTO_eddsa_verify', eddsa_verify: getEmsc('GNUNET_CRYPTO_eddsa_verify',
'number', 'number',
['number', 'number', 'number', 'number']), ['number', 'number', 'number', 'number']),
hash_create_random: getEmsc('GNUNET_CRYPTO_hash_create_random', hash_create_random: getEmsc('GNUNET_CRYPTO_hash_create_random',
'void', 'void',
['number', 'number']), ['number', 'number']),
rsa_blinding_key_destroy: getEmsc('GNUNET_CRYPTO_rsa_blinding_key_free', rsa_blinding_key_destroy: getEmsc('GNUNET_CRYPTO_rsa_blinding_key_free',
'void', 'void',
['number']), ['number']),
random_block: getEmsc('GNUNET_CRYPTO_random_block', random_block: getEmsc('GNUNET_CRYPTO_random_block',
'void', 'void',
['number', 'number', 'number']), ['number', 'number', 'number']),
hash_context_abort: getEmsc('GNUNET_CRYPTO_hash_context_abort', hash_context_abort: getEmsc('GNUNET_CRYPTO_hash_context_abort',
'void', 'void',
['number']), ['number']),
hash_context_read: getEmsc('GNUNET_CRYPTO_hash_context_read', hash_context_read: getEmsc('GNUNET_CRYPTO_hash_context_read',
'void', 'void',
['number', 'number', 'number']), ['number', 'number', 'number']),
hash_context_finish: getEmsc('GNUNET_CRYPTO_hash_context_finish', hash_context_finish: getEmsc('GNUNET_CRYPTO_hash_context_finish',
'void', 'void',
['number', 'number']), ['number', 'number']),
}; };
var emscAlloc = { var emscAlloc = {
get_amount: getEmsc('TALER_WRALL_get_amount', get_amount: getEmsc('TALER_WRALL_get_amount',
'number', 'number',
['number', 'number', 'number', 'string']), ['number', 'number', 'number', 'string']),
eddsa_key_create: getEmsc('GNUNET_CRYPTO_eddsa_key_create', eddsa_key_create: getEmsc('GNUNET_CRYPTO_eddsa_key_create',
'number', []), 'number', []),
ecdsa_key_create: getEmsc('GNUNET_CRYPTO_ecdsa_key_create', ecdsa_key_create: getEmsc('GNUNET_CRYPTO_ecdsa_key_create',
'number', []), 'number', []),
eddsa_public_key_from_private: getEmsc( eddsa_public_key_from_private: getEmsc(
@ -130,41 +130,41 @@ var emscAlloc = {
'number', 'number',
['number']), ['number']),
data_to_string_alloc: getEmsc('GNUNET_STRINGS_data_to_string_alloc', data_to_string_alloc: getEmsc('GNUNET_STRINGS_data_to_string_alloc',
'number', 'number',
['number', 'number']), ['number', 'number']),
purpose_create: getEmsc('TALER_WRALL_purpose_create', purpose_create: getEmsc('TALER_WRALL_purpose_create',
'number', 'number',
['number', 'number', 'number']), ['number', 'number', 'number']),
rsa_blind: getEmsc('GNUNET_CRYPTO_rsa_blind', rsa_blind: getEmsc('GNUNET_CRYPTO_rsa_blind',
'number', 'number',
['number', 'number', 'number', 'number']), ['number', 'number', 'number', 'number', 'number']),
rsa_blinding_key_create: getEmsc('GNUNET_CRYPTO_rsa_blinding_key_create', rsa_blinding_key_create: getEmsc('GNUNET_CRYPTO_rsa_blinding_key_create',
'number', 'number',
['number']), ['number']),
rsa_blinding_key_encode: getEmsc('GNUNET_CRYPTO_rsa_blinding_key_encode', rsa_blinding_key_encode: getEmsc('GNUNET_CRYPTO_rsa_blinding_key_encode',
'number', 'number',
['number', 'number']), ['number', 'number']),
rsa_signature_encode: getEmsc('GNUNET_CRYPTO_rsa_signature_encode', rsa_signature_encode: getEmsc('GNUNET_CRYPTO_rsa_signature_encode',
'number', 'number',
['number', 'number']), ['number', 'number']),
rsa_blinding_key_decode: getEmsc('GNUNET_CRYPTO_rsa_blinding_key_decode', rsa_blinding_key_decode: getEmsc('GNUNET_CRYPTO_rsa_blinding_key_decode',
'number', 'number',
['number', 'number']), ['number', 'number']),
rsa_public_key_decode: getEmsc('GNUNET_CRYPTO_rsa_public_key_decode', rsa_public_key_decode: getEmsc('GNUNET_CRYPTO_rsa_public_key_decode',
'number', 'number',
['number', 'number']), ['number', 'number']),
rsa_signature_decode: getEmsc('GNUNET_CRYPTO_rsa_signature_decode', rsa_signature_decode: getEmsc('GNUNET_CRYPTO_rsa_signature_decode',
'number', 'number',
['number', 'number']), ['number', 'number']),
rsa_public_key_encode: getEmsc('GNUNET_CRYPTO_rsa_public_key_encode', rsa_public_key_encode: getEmsc('GNUNET_CRYPTO_rsa_public_key_encode',
'number', 'number',
['number', 'number']), ['number', 'number']),
rsa_unblind: getEmsc('GNUNET_CRYPTO_rsa_unblind', rsa_unblind: getEmsc('GNUNET_CRYPTO_rsa_unblind',
'number', 'number',
['number', 'number', 'number']), ['number', 'number', 'number']),
hash_context_start: getEmsc('GNUNET_CRYPTO_hash_context_start', hash_context_start: getEmsc('GNUNET_CRYPTO_hash_context_start',
'number', 'number',
[]), []),
malloc: (size: number) => Module._malloc(size), malloc: (size: number) => Module._malloc(size),
}; };
@ -359,9 +359,9 @@ export class Amount extends MallocArenaObject {
super(arena); super(arena);
if (args) { if (args) {
this.nativePtr = emscAlloc.get_amount(args.value, this.nativePtr = emscAlloc.get_amount(args.value,
0, 0,
args.fraction, args.fraction,
args.currency); args.currency);
} else { } else {
this.nativePtr = emscAlloc.get_amount(0, 0, 0, ""); this.nativePtr = emscAlloc.get_amount(0, 0, 0, "");
} }
@ -514,12 +514,12 @@ abstract class PackedArenaObject extends MallocArenaObject {
// to the emscripten heap first. // to the emscripten heap first.
let buf = ByteArray.fromString(s); let buf = ByteArray.fromString(s);
let res = emsc.string_to_data(buf.nativePtr, let res = emsc.string_to_data(buf.nativePtr,
s.length, s.length,
this.nativePtr, this.nativePtr,
this.size()); this.size());
buf.destroy(); buf.destroy();
if (res < 1) { if (res < 1) {
throw { error: "wrong encoding" }; throw {error: "wrong encoding"};
} }
} }
@ -618,7 +618,6 @@ export class EcdsaPrivateKey extends PackedArenaObject {
mixinStatic(EcdsaPrivateKey, fromCrock); mixinStatic(EcdsaPrivateKey, fromCrock);
function fromCrock(s: string) { function fromCrock(s: string) {
let x = new this(); let x = new this();
x.alloc(); x.alloc();
@ -673,7 +672,7 @@ function makeFromCrock(decodeFn: (p: number, s: number) => number) {
let obj = new this(a); let obj = new this(a);
let buf = ByteArray.fromCrock(s); let buf = ByteArray.fromCrock(s);
obj.setNative(decodeFn(buf.getNative(), obj.setNative(decodeFn(buf.getNative(),
buf.size())); buf.size()));
buf.destroy(); buf.destroy();
return obj; return obj;
} }
@ -682,7 +681,7 @@ function makeFromCrock(decodeFn: (p: number, s: number) => number) {
} }
function makeToCrock(encodeFn: (po: number, function makeToCrock(encodeFn: (po: number,
ps: number) => number): () => string { ps: number) => number): () => string {
function toCrock() { function toCrock() {
let ptr = emscAlloc.malloc(PTR_SIZE); let ptr = emscAlloc.malloc(PTR_SIZE);
let size = emscAlloc.rsa_blinding_key_encode(this.nativePtr, ptr); let size = emscAlloc.rsa_blinding_key_encode(this.nativePtr, ptr);
@ -780,12 +779,12 @@ export class EccSignaturePurpose extends PackedArenaObject {
payloadSize: number; payloadSize: number;
constructor(purpose: SignaturePurpose, constructor(purpose: SignaturePurpose,
payload: PackedArenaObject, payload: PackedArenaObject,
a?: Arena) { a?: Arena) {
super(a); super(a);
this.nativePtr = emscAlloc.purpose_create(purpose, this.nativePtr = emscAlloc.purpose_create(purpose,
payload.nativePtr, payload.nativePtr,
payload.size()); payload.size());
this.payloadSize = payload.size(); this.payloadSize = payload.size();
} }
} }
@ -1121,21 +1120,31 @@ mixin(RsaSignature, makeEncode(emscAlloc.rsa_signature_encode));
export function rsaBlind(hashCode: HashCode, export function rsaBlind(hashCode: HashCode,
blindingKey: RsaBlindingKeySecret, blindingKey: RsaBlindingKeySecret,
pkey: RsaPublicKey, pkey: RsaPublicKey,
arena?: Arena): ByteArray { arena?: Arena): ByteArray|null {
let ptr = emscAlloc.malloc(PTR_SIZE); let buf_ptr_out = emscAlloc.malloc(PTR_SIZE);
let s = emscAlloc.rsa_blind(hashCode.nativePtr, let buf_size_out = emscAlloc.malloc(PTR_SIZE);
blindingKey.nativePtr, let res = emscAlloc.rsa_blind(hashCode.nativePtr,
pkey.nativePtr, blindingKey.nativePtr,
ptr); pkey.nativePtr,
return new ByteArray(s, Module.getValue(ptr, '*'), arena); buf_ptr_out,
buf_size_out);
let buf_ptr = Module.getValue(buf_ptr_out, '*');
let buf_size = Module.getValue(buf_size_out, '*');
emsc.free(buf_ptr_out);
emsc.free(buf_size_out);
if (res != GNUNET_OK) {
// malicious key
return null;
}
return new ByteArray(buf_size, buf_ptr, arena);
} }
export function eddsaSign(purpose: EccSignaturePurpose, export function eddsaSign(purpose: EccSignaturePurpose,
priv: EddsaPrivateKey, priv: EddsaPrivateKey,
a?: Arena): EddsaSignature { a?: Arena): EddsaSignature {
let sig = new EddsaSignature(a); let sig = new EddsaSignature(a);
sig.alloc(); sig.alloc();
let res = emsc.eddsa_sign(priv.nativePtr, purpose.nativePtr, sig.nativePtr); let res = emsc.eddsa_sign(priv.nativePtr, purpose.nativePtr, sig.nativePtr);
@ -1147,14 +1156,14 @@ export function eddsaSign(purpose: EccSignaturePurpose,
export function eddsaVerify(purposeNum: number, export function eddsaVerify(purposeNum: number,
verify: EccSignaturePurpose, verify: EccSignaturePurpose,
sig: EddsaSignature, sig: EddsaSignature,
pub: EddsaPublicKey, pub: EddsaPublicKey,
a?: Arena): boolean { a?: Arena): boolean {
let r = emsc.eddsa_verify(purposeNum, let r = emsc.eddsa_verify(purposeNum,
verify.nativePtr, verify.nativePtr,
sig.nativePtr, sig.nativePtr,
pub.nativePtr); pub.nativePtr);
if (r === GNUNET_OK) { if (r === GNUNET_OK) {
return true; return true;
} }
@ -1163,13 +1172,13 @@ export function eddsaVerify(purposeNum: number,
export function rsaUnblind(sig: RsaSignature, export function rsaUnblind(sig: RsaSignature,
bk: RsaBlindingKeySecret, bk: RsaBlindingKeySecret,
pk: RsaPublicKey, pk: RsaPublicKey,
a?: Arena): RsaSignature { a?: Arena): RsaSignature {
let x = new RsaSignature(a); let x = new RsaSignature(a);
x.nativePtr = emscAlloc.rsa_unblind(sig.nativePtr, x.nativePtr = emscAlloc.rsa_unblind(sig.nativePtr,
bk.nativePtr, bk.nativePtr,
pk.nativePtr); pk.nativePtr);
return x; return x;
} }
@ -1208,16 +1217,19 @@ export interface FreshCoin {
blindingKey: RsaBlindingKeySecret; blindingKey: RsaBlindingKeySecret;
} }
export function setupFreshCoin(secretSeed: TransferSecretP, coinIndex: number): FreshCoin { export function setupFreshCoin(secretSeed: TransferSecretP,
coinIndex: number): FreshCoin {
let priv = new EddsaPrivateKey(); let priv = new EddsaPrivateKey();
priv.isWeak = true; priv.isWeak = true;
let blindingKey = new RsaBlindingKeySecret(); let blindingKey = new RsaBlindingKeySecret();
blindingKey.isWeak = true; blindingKey.isWeak = true;
let buf = kdf(priv.size() + blindingKey.size(), UInt32.fromNumber(coinIndex), ByteArray.fromString("taler-coin-derivation")); let buf = kdf(priv.size() + blindingKey.size(),
UInt32.fromNumber(coinIndex),
ByteArray.fromString("taler-coin-derivation"));
priv.nativePtr = buf.nativePtr; priv.nativePtr = buf.nativePtr;
blindingKey.nativePtr = buf.nativePtr + priv.size(); blindingKey.nativePtr = buf.nativePtr + priv.size();
return { priv, blindingKey }; return {priv, blindingKey};
} }

View File

@ -797,8 +797,6 @@ export class Wallet {
} }
async storeCoin(coin: Coin): Promise<void> { async storeCoin(coin: Coin): Promise<void> {
console.log("storing coin", new Date());
let historyEntry: HistoryRecord = { let historyEntry: HistoryRecord = {
type: "withdraw", type: "withdraw",
timestamp: (new Date).getTime(), timestamp: (new Date).getTime(),

View File

@ -286,7 +286,6 @@ class ChromeNotifier implements Notifier {
} }
notify() { notify() {
console.log("notifying all ports");
for (let p of this.ports) { for (let p of this.ports) {
p.postMessage({ notify: true }); p.postMessage({ notify: true });
} }

View File

@ -172,7 +172,7 @@ class ExchangeSelection extends ImplicitStateComponent<ExchangeSelectionProps> {
renderAdvanced(): JSX.Element { renderAdvanced(): JSX.Element {
if (this.detailCollapsed() && this.url() !== null) { if (this.detailCollapsed() && this.url() !== null && !this.statusString()) {
return ( return (
<button className="linky" <button className="linky"
onClick={() => this.detailCollapsed(false)}> onClick={() => this.detailCollapsed(false)}>
@ -224,6 +224,13 @@ class ExchangeSelection extends ImplicitStateComponent<ExchangeSelectionProps> {
<em>{shortName}</em> <em>{shortName}</em>
</p>; </p>;
} }
if (this.statusString()) {
return (
<p>
<strong style="color: red;">A problem occured, see below.</strong>
</p>
);
}
return ( return (
<p> <p>
Information about fees will be available when an exchange provider is selected. Information about fees will be available when an exchange provider is selected.