store reservePub/blindingKey directly in coin

This commit is contained in:
Florian Dold 2017-05-01 04:33:47 +02:00
parent 41ed276f3a
commit 10efd87a8e
No known key found for this signature in database
GPG Key ID: D2E4F00F29D02A4B
7 changed files with 37 additions and 17 deletions

View File

@ -267,8 +267,8 @@ export class CryptoApi {
return this.doRpc<string>("rsaUnblind", 4, sig, bk, pk); return this.doRpc<string>("rsaUnblind", 4, sig, bk, pk);
} }
createPaybackRequest(coin: CoinRecord, preCoin: PreCoinRecord): Promise<PaybackRequest> { createPaybackRequest(coin: CoinRecord): Promise<PaybackRequest> {
return this.doRpc<PaybackRequest>("createPaybackRequest", 1, coin, preCoin); return this.doRpc<PaybackRequest>("createPaybackRequest", 1, coin);
} }
createRefreshSession(exchangeBaseUrl: string, createRefreshSession(exchangeBaseUrl: string,

View File

@ -102,21 +102,18 @@ namespace RpcFunctions {
return preCoin; return preCoin;
} }
export function createPaybackRequest(coin: CoinRecord, preCoin: PreCoinRecord): PaybackRequest { export function createPaybackRequest(coin: CoinRecord): PaybackRequest {
if (coin.coinPub != preCoin.coinPub) {
throw Error("coin doesn't match precoin");
}
let p = new native.PaybackRequestPS({ let p = new native.PaybackRequestPS({
coin_pub: native.EddsaPublicKey.fromCrock(coin.coinPub), coin_pub: native.EddsaPublicKey.fromCrock(coin.coinPub),
h_denom_pub: native.RsaPublicKey.fromCrock(coin.denomPub).encode().hash(), h_denom_pub: native.RsaPublicKey.fromCrock(coin.denomPub).encode().hash(),
coin_blind: native.RsaBlindingKeySecret.fromCrock(preCoin.blindingKey), coin_blind: native.RsaBlindingKeySecret.fromCrock(coin.blindingKey),
}); });
let coinPriv = native.EddsaPrivateKey.fromCrock(coin.coinPriv); let coinPriv = native.EddsaPrivateKey.fromCrock(coin.coinPriv);
let coinSig = native.eddsaSign(p.toPurpose(), coinPriv); let coinSig = native.eddsaSign(p.toPurpose(), coinPriv);
let paybackRequest: PaybackRequest = { let paybackRequest: PaybackRequest = {
denom_pub: coin.denomPub, denom_pub: coin.denomPub,
denom_sig: coin.denomSig, denom_sig: coin.denomSig,
coin_blind_key_secret: preCoin.blindingKey, coin_blind_key_secret: coin.blindingKey,
coin_pub: coin.coinPub, coin_pub: coin.coinPub,
coin_sig: coinSig.toCrock(), coin_sig: coinSig.toCrock(),
}; };

View File

@ -33,7 +33,7 @@ import {
import { ImplicitStateComponent, StateHolder } from "../components"; import { ImplicitStateComponent, StateHolder } from "../components";
import { import {
getReserves, getExchanges, getCoins, getPreCoins, getReserves, getExchanges, getCoins, getPreCoins,
refresh, getDenoms refresh, getDenoms, payback,
} from "../wxApi"; } from "../wxApi";
import { prettyAmount } from "../renderHtml"; import { prettyAmount } from "../renderHtml";
import { getTalerStampDate } from "../helpers"; import { getTalerStampDate } from "../helpers";
@ -135,6 +135,7 @@ class CoinView extends React.Component<CoinViewProps, void> {
<li>Suspended: {(c.suspended || false).toString()}</li> <li>Suspended: {(c.suspended || false).toString()}</li>
<li>Status: {CoinStatus[c.status]}</li> <li>Status: {CoinStatus[c.status]}</li>
<li><RefreshDialog coin={c} /></li> <li><RefreshDialog coin={c} /></li>
<li><button onClick={() => payback(c.coinPub)}>Payback</button></li>
</ul> </ul>
</div> </div>
); );

View File

@ -461,6 +461,14 @@ export interface CoinRecord {
*/ */
suspended?: boolean; suspended?: boolean;
blindingKey: string;
/**
* Reserve public key for the reserve we got this coin from,
* or zero when we got the coin from refresh.
*/
reservePub: string|undefined,
/** /**
* Status of the coin. * Status of the coin.
*/ */

View File

@ -1144,10 +1144,12 @@ export class Wallet {
pc.blindingKey, pc.blindingKey,
pc.denomPub); pc.denomPub);
let coin: CoinRecord = { let coin: CoinRecord = {
reservePub: pc.reservePub,
coinPub: pc.coinPub, coinPub: pc.coinPub,
coinPriv: pc.coinPriv, coinPriv: pc.coinPriv,
denomPub: pc.denomPub, denomPub: pc.denomPub,
denomSig: denomSig, denomSig: denomSig,
blindingKey: pc.blindingKey,
currentAmount: pc.coinValue, currentAmount: pc.coinValue,
exchangeBaseUrl: pc.exchangeBaseUrl, exchangeBaseUrl: pc.exchangeBaseUrl,
status: CoinStatus.Fresh, status: CoinStatus.Fresh,
@ -1971,6 +1973,8 @@ export class Wallet {
pc.blindingKey, pc.blindingKey,
denom.denomPub); denom.denomPub);
let coin: CoinRecord = { let coin: CoinRecord = {
reservePub: undefined,
blindingKey: pc.blindingKey,
coinPub: pc.publicKey, coinPub: pc.publicKey,
coinPriv: pc.privateKey, coinPriv: pc.privateKey,
denomPub: denom.denomPub, denomPub: denom.denomPub,
@ -2128,11 +2132,11 @@ export class Wallet {
if (!coin) { if (!coin) {
throw Error(`Coin ${coinPub} not found, can't request payback`); throw Error(`Coin ${coinPub} not found, can't request payback`);
} }
let preCoin = await this.q().get(Stores.precoins, coin.coinPub); let reservePub = coin.reservePub;
if (!preCoin) { if (!reservePub) {
throw Error(`Precoin of coin ${coinPub} not found`); throw Error(`Can't request payback for a refreshed coin`);
} }
let reserve = await this.q().get(Stores.reserves, preCoin.reservePub); let reserve = await this.q().get(Stores.reserves, reservePub);
if (!reserve) { if (!reserve) {
throw Error(`Reserve of coin ${coinPub} not found`); throw Error(`Reserve of coin ${coinPub} not found`);
} }
@ -2150,14 +2154,14 @@ export class Wallet {
reserve.hasPayback = true; reserve.hasPayback = true;
await this.q().put(Stores.coins, coin).put(Stores.reserves, reserve); await this.q().put(Stores.coins, coin).put(Stores.reserves, reserve);
let paybackRequest = await this.cryptoApi.createPaybackRequest(coin, preCoin); let paybackRequest = await this.cryptoApi.createPaybackRequest(coin);
let reqUrl = new URI("payback").absoluteTo(preCoin.exchangeBaseUrl); let reqUrl = new URI("payback").absoluteTo(coin.exchangeBaseUrl);
let resp = await this.http.get(reqUrl.href()); let resp = await this.http.get(reqUrl.href());
if (resp.status != 200) { if (resp.status != 200) {
throw Error(); throw Error();
} }
let paybackConfirmation = PaybackConfirmation.checked(JSON.parse(resp.responseText)); let paybackConfirmation = PaybackConfirmation.checked(JSON.parse(resp.responseText));
if (paybackConfirmation.reserve_pub != preCoin.reservePub) { if (paybackConfirmation.reserve_pub != coin.reservePub) {
throw Error(`Coin's reserve doesn't match reserve on payback`); throw Error(`Coin's reserve doesn't match reserve on payback`);
} }
coin = await this.q().get(Stores.coins, coinPub); coin = await this.q().get(Stores.coins, coinPub);
@ -2166,7 +2170,7 @@ export class Wallet {
} }
coin.status = CoinStatus.PaybackDone; coin.status = CoinStatus.PaybackDone;
await this.q().put(Stores.coins, coin); await this.q().put(Stores.coins, coin);
await this.updateReserve(preCoin.reservePub); await this.updateReserve(reservePub!);
} }

View File

@ -107,3 +107,7 @@ export async function getDenoms(exchangeBaseUrl: string): Promise<DenominationRe
export async function refresh(coinPub: string): Promise<void> { export async function refresh(coinPub: string): Promise<void> {
return await callBackend("refresh-coin", { coinPub }); return await callBackend("refresh-coin", { coinPub });
} }
export async function payback(coinPub: string): Promise<void> {
return await callBackend("payback-coin", { coinPub });
}

View File

@ -259,6 +259,12 @@ function makeHandlers(db: IDBDatabase,
} }
return wallet.refresh(detail.coinPub); return wallet.refresh(detail.coinPub);
}, },
["payback-coin"]: function (detail, sender) {
if (typeof detail.coinPub !== "string") {
return Promise.reject(Error("coinPub missing"));
}
return wallet.payback(detail.coinPub);
},
["payment-failed"]: function (detail, sender) { ["payment-failed"]: function (detail, sender) {
// For now we just update exchanges (maybe the exchange did something // For now we just update exchanges (maybe the exchange did something
// wrong and the keys were messed up). // wrong and the keys were messed up).