commit 24abcbd76b859c56f1da4115802d2259ca5a8017
parent 686a65234b050d4f2806c7474cad39880664f3b4
Author: Florian Dold <florian@dold.me>
Date: Wed, 7 May 2025 01:19:10 +0200
harness: fix more tests using old refresh
Diffstat:
2 files changed, 76 insertions(+), 55 deletions(-)
diff --git a/packages/taler-util/src/http-client/exchange-client.ts b/packages/taler-util/src/http-client/exchange-client.ts
@@ -55,11 +55,14 @@ import {
ExchangeGetContractResponse,
ExchangeKeysResponse,
ExchangeKycUploadFormRequest,
+ ExchangeMeltRequestV2,
+ ExchangeMeltResponse,
ExchangeMergeConflictResponse,
ExchangeMergeSuccessResponse,
ExchangePurseDeposits,
ExchangePurseMergeRequest,
ExchangePurseStatus,
+ ExchangeRefreshRevealRequestV2,
ExchangeReservePurseRequest,
ExchangeTransferList,
ExchangeVersionResponse,
@@ -83,6 +86,7 @@ import {
codecForExchangeConfig,
codecForExchangeGetContractResponse,
codecForExchangeKeysResponse,
+ codecForExchangeMeltResponse,
codecForExchangeMergeConflictResponse,
codecForExchangeMergeSuccessResponse,
codecForExchangePurseStatus,
@@ -1145,4 +1149,52 @@ export class TalerExchangeHttpClient2 {
return opUnknownHttpFailure(resp);
}
}
+
+ /**
+ * Request: POST /melt
+ *
+ * https://docs.taler.net/core/api-exchange.html#post--melt
+ */
+ async postMelt(args: {
+ body: ExchangeMeltRequestV2;
+ }): Promise<
+ OperationOk<ExchangeMeltResponse> | OperationFail<HttpStatusCode.Forbidden>
+ > {
+ const url = new URL(`melt`, this.baseUrl);
+ const resp = await this.fetch(url, {
+ method: "POST",
+ body: args.body,
+ });
+ // FIXME: Some documented cases are missing.
+ switch (resp.status) {
+ case HttpStatusCode.Ok:
+ return opSuccessFromHttp(resp, codecForExchangeMeltResponse());
+ case HttpStatusCode.Forbidden:
+ return opKnownHttpFailure(resp.status, resp);
+ default:
+ return opUnknownHttpFailure(resp);
+ }
+ }
+
+ async postRevealMelt(args: {
+ body: ExchangeRefreshRevealRequestV2;
+ }): Promise<
+ | OperationOk<ExchangeWithdrawResponse>
+ | OperationFail<HttpStatusCode.Forbidden>
+ > {
+ const url = new URL(`reveal-melt`, this.baseUrl);
+ const resp = await this.fetch(url, {
+ method: "POST",
+ body: args.body,
+ });
+ // FIXME: Some documented cases are missing.
+ switch (resp.status) {
+ case HttpStatusCode.Ok:
+ return opSuccessFromHttp(resp, codecForExchangeWithdrawResponse());
+ case HttpStatusCode.Forbidden:
+ return opKnownHttpFailure(resp.status, resp);
+ default:
+ return opUnknownHttpFailure(resp);
+ }
+ }
}
diff --git a/packages/taler-wallet-core/src/dbless.ts b/packages/taler-wallet-core/src/dbless.ts
@@ -35,8 +35,8 @@ import {
EddsaPrivateKeyString,
EddsaPublicKeyString,
ExchangeBatchDepositRequest,
- ExchangeMeltRequest,
- ExchangeProtocolVersion,
+ ExchangeMeltRequestV2,
+ ExchangeRefreshRevealRequestV2,
Logger,
TalerCorebankApiClient,
TalerExchangeHttpClient2,
@@ -44,11 +44,10 @@ import {
codecForAny,
codecForBankWithdrawalOperationPostResponse,
codecForBatchDepositSuccess,
- codecForExchangeMeltResponse,
- codecForExchangeRevealResponse,
encodeCrock,
getRandomBytes,
hashWire,
+ j2s,
parsePaytoUri,
succeedOrThrow,
} from "@gnu-taler/taler-util";
@@ -60,7 +59,6 @@ import { TalerCryptoInterface } from "./crypto/cryptoImplementation.js";
import { DenominationRecord } from "./db.js";
import { isCandidateWithdrawableDenom } from "./denominations.js";
import { ExchangeInfo, downloadExchangeInfo } from "./exchanges.js";
-import { assembleRefreshRevealRequest } from "./refresh.js";
import { getBankStatusUrl, getBankWithdrawalInfo } from "./withdraw.js";
export { downloadExchangeInfo };
@@ -293,15 +291,14 @@ export async function refreshCoin(req: {
newDenoms: DenominationRecord[];
}): Promise<void> {
const { cryptoApi, oldCoin, http } = req;
- const refreshSessionSeed = encodeCrock(getRandomBytes(32));
- const session = await cryptoApi.deriveRefreshSession({
- exchangeProtocolVersion: ExchangeProtocolVersion.V12,
+ const refreshSessionSeed = encodeCrock(getRandomBytes(64));
+ const session = await cryptoApi.deriveRefreshSessionV2({
feeRefresh: Amounts.parseOrThrow(oldCoin.feeRefresh),
kappa: 3,
meltCoinDenomPubHash: oldCoin.denomPubHash,
meltCoinPriv: oldCoin.coinPriv,
meltCoinPub: oldCoin.coinPub,
- sessionSecretSeed: refreshSessionSeed,
+ sessionPublicSeed: refreshSessionSeed,
newCoinDenoms: req.newDenoms.map((x) => ({
count: 1,
denomPub: x.denomPub,
@@ -312,66 +309,38 @@ export async function refreshCoin(req: {
meltCoinMaxAge: oldCoin.maxAge,
});
- const meltReqBody: ExchangeMeltRequest = {
- coin_pub: oldCoin.coinPub,
+ const meltReqBody: ExchangeMeltRequestV2 = {
+ old_coin_pub: oldCoin.coinPub,
+ old_denom_pub_h: oldCoin.denomPubHash,
+ old_denom_sig: oldCoin.denomSig,
+ // old_age_commitment_h: maybeAch,
+ refresh_seed: refreshSessionSeed,
confirm_sig: session.confirmSig,
- denom_pub_hash: oldCoin.denomPubHash,
- denom_sig: oldCoin.denomSig,
- rc: session.hash,
+ coin_evs: session.planchets.map((x) => x.map((y) => y.coinEv)),
+ denoms_h: req.newDenoms.map((x) => x.denomPubHash),
value_with_fee: Amounts.stringify(session.meltValueWithFee),
};
- logger.info("requesting melt");
-
- const meltReqUrl = new URL(
- `coins/${oldCoin.coinPub}/melt`,
- oldCoin.exchangeBaseUrl,
- );
+ logger.info(`requesting melt: ${j2s(meltReqBody)}`);
- logger.info("requesting melt done");
+ const exchangeClient = new TalerExchangeHttpClient2(oldCoin.exchangeBaseUrl);
- const meltHttpResp = await http.fetch(meltReqUrl.href, {
- method: "POST",
- body: meltReqBody,
- });
-
- const meltResponse = await readSuccessResponseJsonOrThrow(
- meltHttpResp,
- codecForExchangeMeltResponse(),
+ const meltResponse = succeedOrThrow(
+ await exchangeClient.postMelt({ body: meltReqBody }),
);
const norevealIndex = meltResponse.noreveal_index;
- const revealRequest = await assembleRefreshRevealRequest({
- cryptoApi,
- derived: session,
- newDenoms: req.newDenoms.map((x) => ({
- count: 1,
- denomPubHash: x.denomPubHash,
- })),
- norevealIndex,
- oldCoinPriv: oldCoin.coinPriv,
- oldCoinPub: oldCoin.coinPub,
- });
-
- logger.info("requesting reveal");
- const reqUrl = new URL(
- `refreshes/${session.hash}/reveal`,
- oldCoin.exchangeBaseUrl,
- );
+ const revealRequest: ExchangeRefreshRevealRequestV2 = {
+ rc: session.hash,
+ signatures: session.signatures.filter((v, i) => i != norevealIndex),
+ // age_commitment: ...
+ };
- const revealResp = await http.fetch(reqUrl.href, {
- method: "POST",
- body: revealRequest,
- });
+ succeedOrThrow(await exchangeClient.postRevealMelt({ body: revealRequest }));
logger.info("requesting reveal done");
- const reveal = await readSuccessResponseJsonOrThrow(
- revealResp,
- codecForExchangeRevealResponse(),
- );
-
// We could unblind here, but we only use this function to
// benchmark the exchange.
}