aboutsummaryrefslogtreecommitdiff
path: root/extension/lib/wallet/wallet.ts
diff options
context:
space:
mode:
Diffstat (limited to 'extension/lib/wallet/wallet.ts')
-rw-r--r--extension/lib/wallet/wallet.ts272
1 files changed, 120 insertions, 152 deletions
diff --git a/extension/lib/wallet/wallet.ts b/extension/lib/wallet/wallet.ts
index 2d4a29c8d..475d316e3 100644
--- a/extension/lib/wallet/wallet.ts
+++ b/extension/lib/wallet/wallet.ts
@@ -28,6 +28,8 @@ import {Query} from "./query";
import {Checkable} from "./checkable";
import {canonicalizeBaseUrl} from "./helpers";
import {ReserveCreationInfo} from "./types";
+import {PreCoin} from "./types";
+import {Reserve} from "./types";
"use strict";
@@ -65,18 +67,6 @@ export class KeysJson {
}
-export interface PreCoin {
- coinPub: string;
- coinPriv: string;
- reservePub: string;
- denomPub: string;
- blindingKey: string;
- withdrawSig: string;
- coinEv: string;
- mintBaseUrl: string;
- coinValue: AmountJson;
-}
-
export interface Coin {
coinPub: string;
coinPriv: string;
@@ -87,34 +77,6 @@ export interface Coin {
}
-function isValidDenom(denom: Denomination,
- masterPub: string): boolean {
- let p = new native.DenominationKeyValidityPS({
- master: native.EddsaPublicKey.fromCrock(masterPub),
- denom_hash: native.RsaPublicKey.fromCrock(denom.denom_pub).encode().hash(),
- expire_legal: native.AbsoluteTimeNbo.fromTalerString(denom.stamp_expire_legal),
- expire_spend: native.AbsoluteTimeNbo.fromTalerString(denom.stamp_expire_deposit),
- expire_withdraw: native.AbsoluteTimeNbo.fromTalerString(denom.stamp_expire_withdraw),
- start: native.AbsoluteTimeNbo.fromTalerString(denom.stamp_start),
- value: (new native.Amount(denom.value)).toNbo(),
- fee_deposit: (new native.Amount(denom.fee_deposit)).toNbo(),
- fee_refresh: (new native.Amount(denom.fee_refresh)).toNbo(),
- fee_withdraw: (new native.Amount(denom.fee_withdraw)).toNbo(),
- });
-
- let nativeSig = new native.EddsaSignature();
- nativeSig.loadCrock(denom.master_sig);
-
- let nativePub = native.EddsaPublicKey.fromCrock(masterPub);
-
- return native.eddsaVerify(native.SignaturePurpose.MASTER_DENOMINATION_KEY_VALIDITY,
- p.toPurpose(),
- nativeSig,
- nativePub);
-
-}
-
-
class MintInfo implements IMintInfo {
baseUrl: string;
masterPublicKey: string;
@@ -145,53 +107,61 @@ class MintInfo implements IMintInfo {
* mint info is updated with the new information up until
* the first error.
*/
- mergeKeys(newKeys: KeysJson) {
- if (!this.masterPublicKey) {
- this.masterPublicKey = newKeys.master_public_key;
- }
+ mergeKeys(newKeys: KeysJson, wallet: Wallet): Promise<void> {
+ return Promise.resolve().then(() => {
+ if (!this.masterPublicKey) {
+ this.masterPublicKey = newKeys.master_public_key;
+ }
- if (this.masterPublicKey != newKeys.master_public_key) {
- throw Error("public keys do not match");
- }
+ if (this.masterPublicKey != newKeys.master_public_key) {
+ throw Error("public keys do not match");
+ }
- for (let newDenom of newKeys.denoms) {
- let found = false;
- for (let oldDenom of this.denoms) {
- if (oldDenom.denom_pub === newDenom.denom_pub) {
- let a = Object.assign({}, oldDenom);
- let b = Object.assign({}, newDenom);
- // pub hash is only there for convenience in the wallet
- delete a["pub_hash"];
- delete b["pub_hash"];
- if (!_.isEqual(a, b)) {
- console.log("old/new:");
- console.dir(a);
- console.dir(b);
- throw Error("denomination modified");
+ for (let newDenom of newKeys.denoms) {
+ let found = false;
+ for (let oldDenom of this.denoms) {
+ if (oldDenom.denom_pub === newDenom.denom_pub) {
+ let a = Object.assign({}, oldDenom);
+ let b = Object.assign({}, newDenom);
+ // pub hash is only there for convenience in the wallet
+ delete a["pub_hash"];
+ delete b["pub_hash"];
+ if (!_.isEqual(a, b)) {
+ console.log("old/new:");
+ console.dir(a);
+ console.dir(b);
+ throw Error("denomination modified");
+ }
+ // TODO: check if info still matches
+ found = true;
+ break;
}
- // TODO: check if info still matches
- found = true;
- break;
}
- }
- if (found) {
- continue;
- }
+ if (found) {
+ continue;
+ }
- console.log("validating denomination");
+ console.log("validating denomination");
- if (!isValidDenom(newDenom, this.masterPublicKey)) {
- throw Error("signature on denomination invalid");
- }
+ return wallet.isValidDenom(newDenom, this.masterPublicKey)
+ .then((valid) => {
+ if (!valid) {
+ throw Error("signature on denomination invalid");
+ }
- let d: Denomination = Object.assign({}, newDenom);
- d.pub_hash = native.RsaPublicKey.fromCrock(d.denom_pub)
- .encode()
- .hash()
- .toCrock();
- this.denoms.push(d);
- }
+ let d: Denomination = Object.assign({}, newDenom);
+ d.pub_hash = native.RsaPublicKey.fromCrock(d.denom_pub)
+ .encode()
+ .hash()
+ .toCrock();
+ this.denoms.push(d);
+
+ });
+
+ }
+ return;
+ });
}
}
@@ -330,13 +300,6 @@ interface Transaction {
}
-interface Reserve {
- mint_base_url: string
- reserve_priv: string;
- reserve_pub: string;
-}
-
-
export interface Badge {
setText(s: string): void;
setColor(c: string): void;
@@ -395,62 +358,6 @@ function rankDenom(denom1: any, denom2: any) {
}
-function mergeMintKeys(oldKeys: KeysJson, newKeys: KeysJson) {
-}
-
-
-/**
- * Create a pre-coin of the given denomination to be withdrawn from then given
- * reserve.
- */
-function createPreCoin(denom: Denomination, reserve: Reserve): PreCoin {
- let reservePriv = new native.EddsaPrivateKey();
- reservePriv.loadCrock(reserve.reserve_priv);
- let reservePub = new native.EddsaPublicKey();
- reservePub.loadCrock(reserve.reserve_pub);
- let denomPub = native.RsaPublicKey.fromCrock(denom.denom_pub);
- let coinPriv = native.EddsaPrivateKey.create();
- let coinPub = coinPriv.getPublicKey();
- let blindingFactor = native.RsaBlindingKey.create(1024);
- let pubHash: native.HashCode = coinPub.hash();
- let ev: native.ByteArray = native.rsaBlind(pubHash,
- blindingFactor,
- denomPub);
-
- if (!denom.fee_withdraw) {
- throw Error("Field fee_withdraw missing");
- }
-
- let amountWithFee = new native.Amount(denom.value);
- amountWithFee.add(new native.Amount(denom.fee_withdraw));
- let withdrawFee = new native.Amount(denom.fee_withdraw);
-
- // Signature
- let withdrawRequest = new native.WithdrawRequestPS({
- reserve_pub: reservePub,
- amount_with_fee: amountWithFee.toNbo(),
- withdraw_fee: withdrawFee.toNbo(),
- h_denomination_pub: denomPub.encode().hash(),
- h_coin_envelope: ev.hash()
- });
-
- var sig = native.eddsaSign(withdrawRequest.toPurpose(), reservePriv);
-
- let preCoin: PreCoin = {
- reservePub: reservePub.toCrock(),
- blindingKey: blindingFactor.toCrock(),
- coinPub: coinPub.toCrock(),
- coinPriv: coinPriv.toCrock(),
- denomPub: denomPub.encode().toCrock(),
- mintBaseUrl: reserve.mint_base_url,
- withdrawSig: sig.toCrock(),
- coinEv: ev.toCrock(),
- coinValue: denom.value
- };
- return preCoin;
-}
-
-
/**
* Get a list of denominations (with repetitions possible)
* whose total value is as close as possible to the available
@@ -493,6 +400,9 @@ export class Wallet {
private http: HttpRequestLibrary;
private badge: Badge;
private notifier: Notifier;
+ private cryptoWorker: Worker;
+ private nextRpcId: number = 1;
+ private rpcRegistry = {};
constructor(db: IDBDatabase,
@@ -503,6 +413,21 @@ export class Wallet {
this.http = http;
this.badge = badge;
this.notifier = notifier;
+ this.cryptoWorker = new Worker("/lib/wallet/cryptoWorker.js");
+
+ this.cryptoWorker.onmessage = (msg: MessageEvent) => {
+ let id = msg.data.id;
+ if (typeof id !== "number") {
+ console.error("rpc id must be number");
+ return;
+ }
+ if (!this.rpcRegistry[id]) {
+ console.error(`RPC with id ${id} has no registry entry`);
+ return;
+ }
+ let {resolve, reject} = this.rpcRegistry[id];
+ resolve(msg.data.result);
+ }
}
@@ -693,7 +618,9 @@ export class Wallet {
.put("history", historyEntry)
.putAll("coins", payCoinInfo.map((pci) => pci.updatedCoin))
.finish()
- .then(() => { this.notifier.notify(); });
+ .then(() => {
+ this.notifier.notify();
+ });
}
@@ -903,7 +830,9 @@ export class Wallet {
.add("coins", coin)
.add("history", historyEntry)
.finish()
- .then(() => { this.notifier.notify(); });
+ .then(() => {
+ this.notifier.notify();
+ });
}
@@ -912,12 +841,15 @@ export class Wallet {
*/
private withdraw(denom: Denomination, reserve: Reserve): Promise<void> {
console.log("creating pre coin at", new Date());
- let preCoin = createPreCoin(denom, reserve);
- return Query(this.db)
- .put("precoins", preCoin)
- .finish()
- .then(() => this.withdrawExecute(preCoin))
- .then((c) => this.storeCoin(c));
+ return this.createPreCoin(denom, reserve)
+ .then((preCoin) => {
+ return Query(this.db)
+ .put("precoins", preCoin)
+ .finish()
+ .then(() => this.withdrawExecute(preCoin))
+ .then((c) => this.storeCoin(c));
+ });
+
}
@@ -1028,8 +960,14 @@ export class Wallet {
console.log("using old mint");
}
- mint.mergeKeys(mintKeysJson);
- return Query(this.db).put("mints", mint).finish().then(() => mint);
+ return mint.mergeKeys(mintKeysJson)
+ .then(() => {
+ return Query(this.db)
+ .put("mints", mint)
+ .finish()
+ .then(() => mint);
+ });
+
});
});
}
@@ -1070,4 +1008,34 @@ export class Wallet {
.iter("history", {indexName: "timestamp"})
.reduce(collect, [])
}
+
+ registerRpcId(resolve, reject): number {
+ let id = this.nextRpcId++;
+ this.rpcRegistry[id] = {resolve, reject};
+ return id;
+ }
+
+
+ createPreCoin(denom: Denomination, reserve: Reserve): Promise<PreCoin> {
+ return new Promise((resolve, reject) => {
+ let msg = {
+ operation: "createPreCoin",
+ id: this.registerRpcId(resolve, reject),
+ args: [denom, reserve]
+ };
+ this.cryptoWorker.postMessage(msg);
+ });
+ }
+
+ isValidDenom(denom: Denomination,
+ masterPub: string): Promise<boolean> {
+ return new Promise((resolve, reject) => {
+ let msg = {
+ operation: "isValidDenom",
+ id: this.registerRpcId(resolve, reject),
+ args: [denom, masterPub]
+ };
+ this.cryptoWorker.postMessage(msg);
+ });
+ }
} \ No newline at end of file