aboutsummaryrefslogtreecommitdiff
path: root/extension/background/emscriptif.ts
diff options
context:
space:
mode:
Diffstat (limited to 'extension/background/emscriptif.ts')
-rw-r--r--extension/background/emscriptif.ts409
1 files changed, 286 insertions, 123 deletions
diff --git a/extension/background/emscriptif.ts b/extension/background/emscriptif.ts
index f21e60db4..ce6f351c0 100644
--- a/extension/background/emscriptif.ts
+++ b/extension/background/emscriptif.ts
@@ -1,23 +1,23 @@
/*
- This file is part of TALER
- Copyright (C) 2014, 2015 Christian Grothoff (and other contributing authors)
+ This file is part of TALER
+ Copyright (C) 2014, 2015 Christian Grothoff (and other contributing authors)
- 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.
+ 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.
- 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.
+ 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
- TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
-*/
+ You should have received a copy of the GNU General Public License along with
+ TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
+ */
"use strict";
-declare var Module : any;
+declare var Module: any;
// Size of a native pointer.
@@ -30,10 +30,18 @@ const GNUNET_SYSERR = -1;
interface EmscFunGen {
- (name: string, ret: string, args: string[]): ((...x: (number|string)[]) => any);
- (name: string, ret: 'number', args: string[]): ((...x: (number|string)[]) => number);
- (name: string, ret: 'void', args: string[]): ((...x: (number|string)[]) => void);
- (name: string, ret: 'string', args: string[]): ((...x: (number|string)[]) => string);
+ (name: string,
+ ret: string,
+ args: string[]): ((...x: (number|string)[]) => any);
+ (name: string,
+ ret: 'number',
+ args: string[]): ((...x: (number|string)[]) => number);
+ (name: string,
+ ret: 'void',
+ args: string[]): ((...x: (number|string)[]) => void);
+ (name: string,
+ ret: 'string',
+ args: string[]): ((...x: (number|string)[]) => string);
}
let getEmsc: EmscFunGen = (...args) => Module.cwrap.apply(null, args);
@@ -58,15 +66,18 @@ var emsc = {
amount_normalize: getEmsc('TALER_amount_normalize',
'void',
['number']),
+ amount_get_zero: getEmsc('TALER_amount_get_zero',
+ 'number',
+ ['string', 'number']),
amount_cmp: getEmsc('TALER_amount_cmp',
'number',
['number', 'number']),
amount_hton: getEmsc('TALER_amount_hton',
- 'void',
- ['number', 'number']),
+ 'void',
+ ['number', 'number']),
amount_ntoh: getEmsc('TALER_amount_ntoh',
- 'void',
- ['number', 'number']),
+ 'void',
+ ['number', 'number']),
hash: getEmsc('GNUNET_CRYPTO_hash',
'void',
['number', 'number', 'number']),
@@ -77,8 +88,8 @@ var emsc = {
'void',
['number']),
rsa_signature_free: getEmsc('GNUNET_CRYPTO_rsa_signature_free',
- 'void',
- ['number']),
+ 'void',
+ ['number']),
string_to_data: getEmsc('GNUNET_STRINGS_string_to_data',
'number',
['number', 'number', 'number', 'number']),
@@ -89,8 +100,8 @@ var emsc = {
'void',
['number', 'number']),
rsa_blinding_key_destroy: getEmsc('GNUNET_CRYPTO_rsa_blinding_key_free',
- 'void',
- ['number']),
+ 'void',
+ ['number']),
};
var emscAlloc = {
@@ -99,9 +110,10 @@ var emscAlloc = {
['number', 'number', 'number', 'string']),
eddsa_key_create: getEmsc('GNUNET_CRYPTO_eddsa_key_create',
'number', []),
- eddsa_public_key_from_private: getEmsc('TALER_WRALL_eddsa_public_key_from_private',
- 'number',
- ['number']),
+ eddsa_public_key_from_private: getEmsc(
+ 'TALER_WRALL_eddsa_public_key_from_private',
+ 'number',
+ ['number']),
data_to_string_alloc: getEmsc('GNUNET_STRINGS_data_to_string_alloc',
'number',
['number', 'number']),
@@ -112,35 +124,36 @@ var emscAlloc = {
'number',
['number', 'number', 'number', 'number']),
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',
- 'number',
- ['number', 'number']),
+ 'number',
+ ['number', 'number']),
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',
- 'number',
- ['number', 'number']),
+ 'number',
+ ['number', 'number']),
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',
- 'number',
- ['number', 'number']),
+ 'number',
+ ['number', 'number']),
rsa_public_key_encode: getEmsc('GNUNET_CRYPTO_rsa_public_key_encode',
- 'number',
- ['number', 'number']),
+ 'number',
+ ['number', 'number']),
rsa_unblind: getEmsc('GNUNET_CRYPTO_rsa_unblind',
- 'number',
- ['number', 'number', 'number']),
+ 'number',
+ ['number', 'number', 'number']),
malloc: (size: number) => Module._malloc(size),
};
enum SignaturePurpose {
- RESERVE_WITHDRAW = 1200
+ RESERVE_WITHDRAW = 1200,
+ WALLET_COIN_DEPOSIT = 1201,
}
enum RandomQuality {
@@ -153,6 +166,7 @@ enum RandomQuality {
abstract class ArenaObject {
private _nativePtr: number;
arena: Arena;
+
abstract destroy(): void;
constructor(arena?: Arena) {
@@ -172,7 +186,7 @@ abstract class ArenaObject {
// of native wrappers, but we never want to
// pass 'undefined' to emscripten.
if (this._nativePtr === undefined) {
- throw Error("Native pointer not initialized");
+ throw Error("Native pointer not initialized");
}
return this._nativePtr;
}
@@ -198,11 +212,11 @@ abstract class ArenaObject {
this._nativePtr = n;
}
- set nativePtr (v) {
+ set nativePtr(v) {
this.setNative(v);
}
- get nativePtr () {
+ get nativePtr() {
return this.getNative();
}
@@ -215,6 +229,7 @@ interface Arena {
class DefaultArena implements Arena {
heap: Array<ArenaObject>;
+
constructor() {
this.heap = [];
}
@@ -238,31 +253,35 @@ class DefaultArena implements Arena {
*/
class SyncArena extends DefaultArena {
timer: Worker;
+
constructor() {
super();
let me = this;
this.timer = new Worker('background/timerThread.js');
- this.timer.onmessage = (e) => {
+ this.timer.onmessage = () => {
this.destroy();
};
//this.timer.postMessage({interval: 50});
}
+
destroy() {
super.destroy();
}
}
-
let arenaStack: Arena[] = [];
arenaStack.push(new SyncArena());
class Amount extends ArenaObject {
- constructor(args?: any, arena?: Arena) {
+ constructor(args?: AmountJson, arena?: Arena) {
super(arena);
if (args) {
- this.nativePtr = emscAlloc.get_amount(args.value, 0, args.fraction, args.currency);
+ this.nativePtr = emscAlloc.get_amount(args.value,
+ 0,
+ args.fraction,
+ args.currency);
} else {
this.nativePtr = emscAlloc.get_amount(0, 0, 0, "");
}
@@ -274,6 +293,17 @@ class Amount extends ArenaObject {
}
}
+
+ static getZero(currency: string, a?: Arena) {
+ let am = new Amount(null, a);
+ let r = emsc.amount_get_zero(currency, am.getNative());
+ if (r != GNUNET_OK) {
+ throw Error("invalid currency");
+ }
+ return am;
+ }
+
+
toNbo(a?: Arena): AmountNbo {
let x = new AmountNbo(a);
x.alloc();
@@ -362,7 +392,10 @@ abstract class PackedArenaObject extends ArenaObject {
// We need to get the javascript string
// to the emscripten heap first.
let buf = ByteArray.fromString(s);
- let res = emsc.string_to_data(buf.nativePtr, s.length, this.nativePtr, this.size());
+ let res = emsc.string_to_data(buf.nativePtr,
+ s.length,
+ this.nativePtr,
+ this.size());
buf.destroy();
if (res < 1) {
throw {error: "wrong encoding"};
@@ -390,7 +423,9 @@ abstract class PackedArenaObject extends ArenaObject {
class AmountNbo extends PackedArenaObject {
- size() { return 24; }
+ size() {
+ return 24;
+ }
}
@@ -401,37 +436,76 @@ class EddsaPrivateKey extends PackedArenaObject {
return obj;
}
- size() { return 32; }
+ size() {
+ return 32;
+ }
getPublicKey(a?: Arena): EddsaPublicKey {
let obj = new EddsaPublicKey(a);
obj.nativePtr = emscAlloc.eddsa_public_key_from_private(this.nativePtr);
return obj;
}
+
+ static fromCrock: (string) => EddsaPrivateKey;
}
+mixinStatic(EddsaPrivateKey, fromCrock);
-class EddsaPublicKey extends PackedArenaObject {
- size() { return 32; }
+function fromCrock(s: string) {
+ let x = new this();
+ x.alloc();
+ x.loadCrock(s);
+ return x;
+}
+
+
+function mixin(obj, method, name?: string) {
+ if (!name) {
+ name = method.name;
+ }
+ if (!name) {
+ throw Error("Mixin needs a name.");
+ }
+ console.log("mixing in", name, "into", obj.name);
+ obj.prototype[method.name] = method;
}
+function mixinStatic(obj, method, name?: string) {
+ if (!name) {
+ name = method.name;
+ }
+ if (!name) {
+ throw Error("Mixin needs a name.");
+ }
+ console.log("mixing in", name, "into", obj.name);
+ obj[method.name] = method;
+}
-class RsaBlindingKey extends ArenaObject {
- static create(len: number, a?: Arena) {
- let o = new RsaBlindingKey(a);
- o.nativePtr = emscAlloc.rsa_blinding_key_create(len);
- return o;
+
+class EddsaPublicKey extends PackedArenaObject {
+ size() {
+ return 32;
}
- static fromCrock(s: string, a?: Arena): RsaBlindingKey {
+ static fromCrock: (s: string) => EddsaPublicKey;
+}
+mixinStatic(EddsaPublicKey, fromCrock);
+
+function makeFromCrock(decodeFn: (p: number, s: number) => number) {
+ function fromCrock(s: string, a?: Arena) {
let obj = new this(a);
let buf = ByteArray.fromCrock(s);
- obj.setNative(emscAlloc.rsa_blinding_key_decode(buf.getNative(), buf.size()));
+ obj.setNative(decodeFn(buf.getNative(),
+ buf.size()));
buf.destroy();
return obj;
}
- toCrock(): string {
+ return fromCrock;
+}
+
+function makeToCrock(encodeFn: (po: number, ps: number) => number): () => string {
+ function toCrock() {
let ptr = emscAlloc.malloc(PTR_SIZE);
let size = emscAlloc.rsa_blinding_key_encode(this.nativePtr, ptr);
let res = new ByteArray(size, Module.getValue(ptr, '*'));
@@ -440,15 +514,32 @@ class RsaBlindingKey extends ArenaObject {
res.destroy();
return s;
}
+ return toCrock;
+}
+
+class RsaBlindingKey extends ArenaObject {
+ static create(len: number, a?: Arena) {
+ let o = new RsaBlindingKey(a);
+ o.nativePtr = emscAlloc.rsa_blinding_key_create(len);
+ return o;
+ }
+
+ static fromCrock: (s: string, a?: Arena) => RsaBlindingKey;
+ toCrock = makeToCrock(emscAlloc.rsa_blinding_key_encode);
destroy() {
// TODO
}
}
+mixinStatic(RsaBlindingKey, makeFromCrock(emscAlloc.rsa_blinding_key_decode));
class HashCode extends PackedArenaObject {
- size() { return 64; }
+ size() {
+ return 64;
+ }
+
+ static fromCrock: (s: string) => HashCode;
random(qualStr: string) {
let qual: RandomQuality;
@@ -472,11 +563,15 @@ class HashCode extends PackedArenaObject {
emsc.hash_create_random(qual, this.nativePtr);
}
}
+mixinStatic(HashCode, fromCrock);
class ByteArray extends PackedArenaObject {
private allocatedSize: number;
- size() { return this.allocatedSize; }
+
+ size() {
+ return this.allocatedSize;
+ }
constructor(desiredSize: number, init: number, a?: Arena) {
super(a);
@@ -510,11 +605,19 @@ class ByteArray extends PackedArenaObject {
class EccSignaturePurpose extends PackedArenaObject {
- size() { return this.payloadSize + 8; }
+ size() {
+ return this.payloadSize + 8;
+ }
+
payloadSize: number;
- constructor(purpose: SignaturePurpose, payload: PackedArenaObject, a?: Arena) {
+
+ constructor(purpose: SignaturePurpose,
+ payload: PackedArenaObject,
+ a?: Arena) {
super(a);
- this.nativePtr = emscAlloc.purpose_create(purpose, payload.nativePtr, payload.size());
+ this.nativePtr = emscAlloc.purpose_create(purpose,
+ payload.nativePtr,
+ payload.size());
this.payloadSize = payload.size();
}
}
@@ -522,7 +625,9 @@ class EccSignaturePurpose extends PackedArenaObject {
abstract class SignatureStruct {
abstract fieldTypes(): Array<any>;
+
abstract purpose(): SignaturePurpose;
+
private members: any = {};
constructor(x: { [name: string]: any }) {
@@ -552,12 +657,11 @@ abstract class SignatureStruct {
ptr += size;
}
let ba = new ByteArray(totalSize, buf, a);
- let x = new EccSignaturePurpose(this.purpose(), ba);
- return x;
+ return new EccSignaturePurpose(this.purpose(), ba);
}
protected set(name: string, value: PackedArenaObject) {
- let typemap: any = {}
+ let typemap: any = {};
for (let f of this.fieldTypes()) {
typemap[f[0]] = f[1];
}
@@ -586,98 +690,156 @@ class WithdrawRequestPS extends SignatureStruct {
constructor(w: WithdrawRequestPS_Args) {
super(w);
}
- purpose() { return SignaturePurpose.RESERVE_WITHDRAW; }
+
+ purpose() {
+ return SignaturePurpose.RESERVE_WITHDRAW;
+ }
+
fieldTypes() {
return [
- ["reserve_pub", EddsaPublicKey],
- ["amount_with_fee", AmountNbo],
- ["withdraw_fee", AmountNbo],
- ["h_denomination_pub", HashCode],
- ["h_coin_envelope", HashCode]];
+ ["reserve_pub", EddsaPublicKey],
+ ["amount_with_fee", AmountNbo],
+ ["withdraw_fee", AmountNbo],
+ ["h_denomination_pub", HashCode],
+ ["h_coin_envelope", HashCode]
+ ];
}
}
+class AbsoluteTimeNbo extends PackedArenaObject {
+ static fromTalerString(s: string): AbsoluteTimeNbo {
+ throw Error();
+ }
-function encodeWith(obj, fn, arena?: Arena) {
- let ptr = emscAlloc.malloc(PTR_SIZE);
- let len = fn(obj.getNative(), ptr);
- let res = new ByteArray(len, null, arena);
- res.setNative(Module.getValue(ptr, '*'));
- emsc.free(ptr);
- return res;
+ size() {
+ return 8;
+ }
}
-class RsaPublicKey extends ArenaObject {
- static fromCrock(s: string, a?: Arena): RsaPublicKey {
- let obj = new RsaPublicKey(a);
- let buf = ByteArray.fromCrock(s);
- obj.nativePtr = emscAlloc.rsa_public_key_decode(buf.nativePtr, buf.size());
- buf.destroy();
- return obj;
+class UInt64 extends PackedArenaObject {
+ static fromNumber(n: number): UInt64 {
+ throw Error();
}
- toCrock() {
- return this.encode().toCrock();
+ size() {
+ return 8;
}
+}
- destroy() {
- emsc.rsa_public_key_free(this.nativePtr);
- this.nativePtr = 0;
+
+// It's redundant, but more type safe.
+interface DepositRequestPS_Args {
+ h_contract: HashCode;
+ h_wire: HashCode;
+ timestamp: AbsoluteTimeNbo;
+ refund_deadline: AbsoluteTimeNbo;
+ transaction_id: UInt64;
+ amount_with_fee: AmountNbo;
+ deposit_fee: AmountNbo;
+ merchant: EddsaPublicKey;
+ coin_pub: EddsaPublicKey;
+}
+
+
+class DepositRequestPS extends SignatureStruct {
+ constructor(w: DepositRequestPS_Args) {
+ super(w);
+ }
+
+ purpose() {
+ return SignaturePurpose.WALLET_COIN_DEPOSIT;
}
- encode(arena?: Arena): ByteArray {
+ fieldTypes() {
+ return [
+ ["h_contract", HashCode],
+ ["h_wire", HashCode],
+ ["timestamp", AbsoluteTimeNbo],
+ ["refund_deadline", AbsoluteTimeNbo],
+ ["transaction_id", UInt64],
+ ["amount_with_fee", AmountNbo],
+ ["deposit_fee", AmountNbo],
+ ["merchant", EddsaPublicKey],
+ ["coin_pub", EddsaPublicKey],
+ ];
+ }
+}
+
+
+interface Encodeable {
+ encode(arena?: Arena): ByteArray;
+}
+
+function makeEncode(encodeFn) {
+ function encode(arena?: Arena) {
let ptr = emscAlloc.malloc(PTR_SIZE);
- let len = emscAlloc.rsa_public_key_encode(this.nativePtr, ptr);
- let res = new ByteArray(len, Module.getValue(ptr, '*'), arena);
+ let len = encodeFn(this.getNative(), ptr);
+ let res = new ByteArray(len, null, arena);
+ res.setNative(Module.getValue(ptr, '*'));
emsc.free(ptr);
return res;
}
+ return encode;
+}
+
+
+class RsaPublicKey extends ArenaObject implements Encodeable {
+ static fromCrock: (s: string, a?: Arena) => RsaPublicKey;
+
+ toCrock() {
+ return this.encode().toCrock();
+ }
+ destroy() {
+ emsc.rsa_public_key_free(this.nativePtr);
+ this.nativePtr = 0;
+ }
+
+ encode: (arena?: Arena) => ByteArray;
}
+mixinStatic(RsaPublicKey, makeFromCrock(emscAlloc.rsa_public_key_decode));
+mixin(RsaPublicKey, makeEncode(emscAlloc.rsa_public_key_encode));
class EddsaSignature extends PackedArenaObject {
- size() { return 64; }
+ size() {
+ return 64;
+ }
}
-class RsaSignature extends ArenaObject {
- static fromCrock(s: string, a?: Arena): RsaSignature {
- let obj = new this(a);
- let buf = ByteArray.fromCrock(s);
- obj.setNative(emscAlloc.rsa_signature_decode(buf.getNative(), buf.size()));
- buf.destroy();
- return obj;
- }
+class RsaSignature extends ArenaObject implements Encodeable{
+ static fromCrock: (s: string, a?: Arena) => RsaSignature;
- encode(arena?: Arena): ByteArray {
- return encodeWith(this, emscAlloc.rsa_signature_encode);
- }
+ encode: (arena?: Arena) => ByteArray;
destroy() {
emsc.rsa_signature_free(this.getNative());
this.setNative(0);
}
}
+mixinStatic(RsaSignature, makeFromCrock(emscAlloc.rsa_signature_decode));
+mixin(RsaSignature, makeEncode(emscAlloc.rsa_signature_encode));
+
function rsaBlind(hashCode: HashCode,
- blindingKey: RsaBlindingKey,
+ blindingKey: RsaBlindingKey,
pkey: RsaPublicKey,
- arena?: Arena): ByteArray
-{
+ arena?: Arena): ByteArray {
let ptr = emscAlloc.malloc(PTR_SIZE);
- let s = emscAlloc.rsa_blind(hashCode.nativePtr, blindingKey.nativePtr, pkey.nativePtr, ptr);
- let res = new ByteArray(s, Module.getValue(ptr, '*'), arena);
- return res;
+ let s = emscAlloc.rsa_blind(hashCode.nativePtr,
+ blindingKey.nativePtr,
+ pkey.nativePtr,
+ ptr);
+ return new ByteArray(s, Module.getValue(ptr, '*'), arena);
}
function eddsaSign(purpose: EccSignaturePurpose,
priv: EddsaPrivateKey,
- a?: Arena): EddsaSignature
-{
+ a?: Arena): EddsaSignature {
let sig = new EddsaSignature(a);
sig.alloc();
let res = emsc.eddsa_sign(priv.nativePtr, purpose.nativePtr, sig.nativePtr);
@@ -687,13 +849,14 @@ function eddsaSign(purpose: EccSignaturePurpose,
return sig;
}
+
function rsaUnblind(sig: RsaSignature,
bk: RsaBlindingKey,
pk: RsaPublicKey,
a?: Arena): RsaSignature {
let x = new RsaSignature(a);
- x.nativePtr = emscAlloc.rsa_unblind(sig.nativePtr, bk.nativePtr, pk.nativePtr);
+ x.nativePtr = emscAlloc.rsa_unblind(sig.nativePtr,
+ bk.nativePtr,
+ pk.nativePtr);
return x;
}
-
-