wallet-core: towards exchange protocol v12
This commit is contained in:
parent
188ff0b453
commit
a7b89247e4
@ -1620,3 +1620,9 @@ export const codecForMerchantConfigResponse = (): Codec<MerchantConfigResponse>
|
|||||||
.property("name", codecForString())
|
.property("name", codecForString())
|
||||||
.property("version", codecForString())
|
.property("version", codecForString())
|
||||||
.build("MerchantConfigResponse");
|
.build("MerchantConfigResponse");
|
||||||
|
|
||||||
|
|
||||||
|
export enum ExchangeProtocolVersion {
|
||||||
|
V9 = 9,
|
||||||
|
V12 = 12,
|
||||||
|
}
|
||||||
|
@ -4,7 +4,8 @@ import nodeResolve from "@rollup/plugin-node-resolve";
|
|||||||
import json from "@rollup/plugin-json";
|
import json from "@rollup/plugin-json";
|
||||||
import builtins from "builtin-modules";
|
import builtins from "builtin-modules";
|
||||||
import pkg from "./package.json";
|
import pkg from "./package.json";
|
||||||
import sourcemaps from 'rollup-plugin-sourcemaps';
|
import sourcemaps from "rollup-plugin-sourcemaps";
|
||||||
|
import path from "path";
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
input: "lib/index.js",
|
input: "lib/index.js",
|
||||||
@ -12,6 +13,15 @@ export default {
|
|||||||
file: pkg.main,
|
file: pkg.main,
|
||||||
format: "cjs",
|
format: "cjs",
|
||||||
sourcemap: true,
|
sourcemap: true,
|
||||||
|
sourcemapPathTransform: (relativeSourcePath, sourcemapPath) => {
|
||||||
|
// Transform to source map paths to virtual path. Otherwise,
|
||||||
|
// error messages would contain paths that look like they should exist (relative to
|
||||||
|
// the bundle) but don't.
|
||||||
|
const res = path.normalize(
|
||||||
|
path.join("/_walletsrc/packages/taler-wallet-cli/src/", relativeSourcePath),
|
||||||
|
);
|
||||||
|
return res;
|
||||||
|
},
|
||||||
},
|
},
|
||||||
external: builtins,
|
external: builtins,
|
||||||
plugins: [
|
plugins: [
|
||||||
@ -29,5 +39,4 @@ export default {
|
|||||||
|
|
||||||
json(),
|
json(),
|
||||||
],
|
],
|
||||||
}
|
};
|
||||||
|
|
||||||
|
@ -27,7 +27,7 @@
|
|||||||
/**
|
/**
|
||||||
* Imports.
|
* Imports.
|
||||||
*/
|
*/
|
||||||
import { AmountJson, DenominationPubKey } from "@gnu-taler/taler-util";
|
import { AmountJson, DenominationPubKey, ExchangeProtocolVersion } from "@gnu-taler/taler-util";
|
||||||
|
|
||||||
export interface RefreshNewDenomInfo {
|
export interface RefreshNewDenomInfo {
|
||||||
count: number;
|
count: number;
|
||||||
@ -41,6 +41,7 @@ export interface RefreshNewDenomInfo {
|
|||||||
* secret seed.
|
* secret seed.
|
||||||
*/
|
*/
|
||||||
export interface DeriveRefreshSessionRequest {
|
export interface DeriveRefreshSessionRequest {
|
||||||
|
exchangeProtocolVersion: ExchangeProtocolVersion;
|
||||||
sessionSecretSeed: string;
|
sessionSecretSeed: string;
|
||||||
kappa: number;
|
kappa: number;
|
||||||
meltCoinPub: string;
|
meltCoinPub: string;
|
||||||
|
@ -36,6 +36,7 @@ import {
|
|||||||
buildSigPS,
|
buildSigPS,
|
||||||
CoinDepositPermission,
|
CoinDepositPermission,
|
||||||
DenomKeyType,
|
DenomKeyType,
|
||||||
|
ExchangeProtocolVersion,
|
||||||
FreshCoin,
|
FreshCoin,
|
||||||
hashDenomPub,
|
hashDenomPub,
|
||||||
RecoupRequest,
|
RecoupRequest,
|
||||||
@ -162,7 +163,7 @@ async function myEddsaSign(
|
|||||||
export class CryptoImplementation {
|
export class CryptoImplementation {
|
||||||
static enableTracing = false;
|
static enableTracing = false;
|
||||||
|
|
||||||
constructor(private primitiveWorker?: PrimitiveWorker) { }
|
constructor(private primitiveWorker?: PrimitiveWorker) {}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a pre-coin of the given denomination to be withdrawn from then given
|
* Create a pre-coin of the given denomination to be withdrawn from then given
|
||||||
@ -364,18 +365,18 @@ export class CryptoImplementation {
|
|||||||
}
|
}
|
||||||
|
|
||||||
isValidWireAccount(
|
isValidWireAccount(
|
||||||
versionCurrent: number,
|
versionCurrent: ExchangeProtocolVersion,
|
||||||
paytoUri: string,
|
paytoUri: string,
|
||||||
sig: string,
|
sig: string,
|
||||||
masterPub: string,
|
masterPub: string,
|
||||||
): boolean {
|
): boolean {
|
||||||
if (versionCurrent === 10 || versionCurrent === 11) {
|
if (versionCurrent === ExchangeProtocolVersion.V12) {
|
||||||
const paytoHash = hash(stringToBytes(paytoUri + "\0"));
|
const paytoHash = hash(stringToBytes(paytoUri + "\0"));
|
||||||
const p = buildSigPS(TalerSignaturePurpose.MASTER_WIRE_DETAILS)
|
const p = buildSigPS(TalerSignaturePurpose.MASTER_WIRE_DETAILS)
|
||||||
.put(paytoHash)
|
.put(paytoHash)
|
||||||
.build();
|
.build();
|
||||||
return eddsaVerify(p, decodeCrock(sig), decodeCrock(masterPub));
|
return eddsaVerify(p, decodeCrock(sig), decodeCrock(masterPub));
|
||||||
} else if (versionCurrent === 9) {
|
} else if (versionCurrent === ExchangeProtocolVersion.V9) {
|
||||||
const h = kdf(
|
const h = kdf(
|
||||||
64,
|
64,
|
||||||
stringToBytes("exchange-wire-signature"),
|
stringToBytes("exchange-wire-signature"),
|
||||||
@ -623,13 +624,27 @@ export class CryptoImplementation {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const sessionHash = sessionHc.finish();
|
const sessionHash = sessionHc.finish();
|
||||||
const confirmData = buildSigPS(TalerSignaturePurpose.WALLET_COIN_MELT)
|
let confirmData: Uint8Array;
|
||||||
.put(sessionHash)
|
if (req.exchangeProtocolVersion === ExchangeProtocolVersion.V9) {
|
||||||
.put(decodeCrock(meltCoinDenomPubHash))
|
confirmData = buildSigPS(TalerSignaturePurpose.WALLET_COIN_MELT)
|
||||||
.put(amountToBuffer(valueWithFee))
|
.put(sessionHash)
|
||||||
.put(amountToBuffer(meltFee))
|
.put(decodeCrock(meltCoinDenomPubHash))
|
||||||
.put(decodeCrock(meltCoinPub))
|
.put(amountToBuffer(valueWithFee))
|
||||||
.build();
|
.put(amountToBuffer(meltFee))
|
||||||
|
.put(decodeCrock(meltCoinPub))
|
||||||
|
.build();
|
||||||
|
} else if (req.exchangeProtocolVersion === ExchangeProtocolVersion.V12) {
|
||||||
|
confirmData = buildSigPS(TalerSignaturePurpose.WALLET_COIN_MELT)
|
||||||
|
.put(sessionHash)
|
||||||
|
.put(decodeCrock(meltCoinDenomPubHash))
|
||||||
|
.put(amountToBuffer(valueWithFee))
|
||||||
|
.put(amountToBuffer(meltFee))
|
||||||
|
.build();
|
||||||
|
} else {
|
||||||
|
throw Error(
|
||||||
|
`Exchange protocol version (${req.exchangeProtocolVersion}) not supported`,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
const confirmSigResp = await myEddsaSign(this.primitiveWorker, {
|
const confirmSigResp = await myEddsaSign(this.primitiveWorker, {
|
||||||
msg: encodeCrock(confirmData),
|
msg: encodeCrock(confirmData),
|
||||||
|
@ -17,6 +17,7 @@
|
|||||||
import {
|
import {
|
||||||
DenomKeyType,
|
DenomKeyType,
|
||||||
encodeCrock,
|
encodeCrock,
|
||||||
|
ExchangeProtocolVersion,
|
||||||
getRandomBytes,
|
getRandomBytes,
|
||||||
HttpStatusCode,
|
HttpStatusCode,
|
||||||
} from "@gnu-taler/taler-util";
|
} from "@gnu-taler/taler-util";
|
||||||
@ -91,8 +92,10 @@ export function getTotalRefreshCost(
|
|||||||
refreshedDenom: DenominationRecord,
|
refreshedDenom: DenominationRecord,
|
||||||
amountLeft: AmountJson,
|
amountLeft: AmountJson,
|
||||||
): AmountJson {
|
): AmountJson {
|
||||||
const withdrawAmount = Amounts.sub(amountLeft, refreshedDenom.feeRefresh)
|
const withdrawAmount = Amounts.sub(
|
||||||
.amount;
|
amountLeft,
|
||||||
|
refreshedDenom.feeRefresh,
|
||||||
|
).amount;
|
||||||
const withdrawDenoms = selectWithdrawalDenominations(withdrawAmount, denoms);
|
const withdrawDenoms = selectWithdrawalDenominations(withdrawAmount, denoms);
|
||||||
const resultingAmount = Amounts.add(
|
const resultingAmount = Amounts.add(
|
||||||
Amounts.getZero(withdrawAmount.currency),
|
Amounts.getZero(withdrawAmount.currency),
|
||||||
@ -198,9 +201,10 @@ async function refreshCreateSession(
|
|||||||
}
|
}
|
||||||
|
|
||||||
// FIXME: use an index here, based on the withdrawal expiration time.
|
// FIXME: use an index here, based on the withdrawal expiration time.
|
||||||
const availableDenoms: DenominationRecord[] = await tx.denominations.indexes.byExchangeBaseUrl
|
const availableDenoms: DenominationRecord[] =
|
||||||
.iter(exchange.baseUrl)
|
await tx.denominations.indexes.byExchangeBaseUrl
|
||||||
.toArray();
|
.iter(exchange.baseUrl)
|
||||||
|
.toArray();
|
||||||
|
|
||||||
const availableAmount = Amounts.sub(
|
const availableAmount = Amounts.sub(
|
||||||
refreshGroup.inputPerCoin[coinIndex],
|
refreshGroup.inputPerCoin[coinIndex],
|
||||||
@ -351,7 +355,22 @@ async function refreshMelt(
|
|||||||
|
|
||||||
const { newCoinDenoms, oldCoin, oldDenom, refreshGroup, refreshSession } = d;
|
const { newCoinDenoms, oldCoin, oldDenom, refreshGroup, refreshSession } = d;
|
||||||
|
|
||||||
|
let exchangeProtocolVersion: ExchangeProtocolVersion;
|
||||||
|
switch (d.oldDenom.denomPub.cipher) {
|
||||||
|
case DenomKeyType.LegacyRsa: {
|
||||||
|
exchangeProtocolVersion = ExchangeProtocolVersion.V9;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case DenomKeyType.Rsa: {
|
||||||
|
exchangeProtocolVersion = ExchangeProtocolVersion.V12;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
throw Error("unsupported key type");
|
||||||
|
}
|
||||||
|
|
||||||
const derived = await ws.cryptoApi.deriveRefreshSession({
|
const derived = await ws.cryptoApi.deriveRefreshSession({
|
||||||
|
exchangeProtocolVersion,
|
||||||
kappa: 3,
|
kappa: 3,
|
||||||
meltCoinDenomPubHash: oldCoin.denomPubHash,
|
meltCoinDenomPubHash: oldCoin.denomPubHash,
|
||||||
meltCoinPriv: oldCoin.coinPriv,
|
meltCoinPriv: oldCoin.coinPriv,
|
||||||
@ -531,7 +550,22 @@ async function refreshReveal(
|
|||||||
norevealIndex,
|
norevealIndex,
|
||||||
} = d;
|
} = d;
|
||||||
|
|
||||||
|
let exchangeProtocolVersion: ExchangeProtocolVersion;
|
||||||
|
switch (d.oldDenom.denomPub.cipher) {
|
||||||
|
case DenomKeyType.LegacyRsa: {
|
||||||
|
exchangeProtocolVersion = ExchangeProtocolVersion.V9;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case DenomKeyType.Rsa: {
|
||||||
|
exchangeProtocolVersion = ExchangeProtocolVersion.V12;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
throw Error("unsupported key type");
|
||||||
|
}
|
||||||
|
|
||||||
const derived = await ws.cryptoApi.deriveRefreshSession({
|
const derived = await ws.cryptoApi.deriveRefreshSession({
|
||||||
|
exchangeProtocolVersion,
|
||||||
kappa: 3,
|
kappa: 3,
|
||||||
meltCoinDenomPubHash: oldCoin.denomPubHash,
|
meltCoinDenomPubHash: oldCoin.denomPubHash,
|
||||||
meltCoinPriv: oldCoin.coinPriv,
|
meltCoinPriv: oldCoin.coinPriv,
|
||||||
|
@ -19,7 +19,7 @@
|
|||||||
*
|
*
|
||||||
* Uses libtool's current:revision:age versioning.
|
* Uses libtool's current:revision:age versioning.
|
||||||
*/
|
*/
|
||||||
export const WALLET_EXCHANGE_PROTOCOL_VERSION = "10:0:1";
|
export const WALLET_EXCHANGE_PROTOCOL_VERSION = "12:0:0";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Protocol version spoken with the merchant.
|
* Protocol version spoken with the merchant.
|
||||||
|
Loading…
Reference in New Issue
Block a user