From dc596f1f4d494c3bf9e57253d773205dc0479179 Mon Sep 17 00:00:00 2001 From: Florian Dold Date: Wed, 12 Jan 2022 15:51:56 +0100 Subject: implement latest recoup protocol --- packages/taler-util/src/talerTypes.ts | 10 -------- .../taler-wallet-core/src/crypto/cryptoTypes.ts | 2 -- .../src/crypto/workers/cryptoImplementation.ts | 18 ++++++--------- packages/taler-wallet-core/src/db.ts | 15 ++++++------ .../src/operations/backup/import.ts | 1 - .../taler-wallet-core/src/operations/recoup.ts | 27 +++++++++++----------- .../taler-wallet-core/src/operations/reserves.ts | 2 -- packages/taler-wallet-core/src/util/http.ts | 4 ++-- 8 files changed, 31 insertions(+), 48 deletions(-) diff --git a/packages/taler-util/src/talerTypes.ts b/packages/taler-util/src/talerTypes.ts index 5f72e08ce..41aa53fd4 100644 --- a/packages/taler-util/src/talerTypes.ts +++ b/packages/taler-util/src/talerTypes.ts @@ -173,11 +173,6 @@ export interface RecoupRequest { * Signature of TALER_RecoupRequestPS created with the coin's private key. */ coin_sig: string; - - /** - * Amount being recouped. - */ - amount: AmountString; } export interface RecoupRefreshRequest { @@ -204,11 +199,6 @@ export interface RecoupRefreshRequest { * the coin's private key. */ coin_sig: string; - - /** - * Amount being recouped. - */ - amount: AmountString; } /** diff --git a/packages/taler-wallet-core/src/crypto/cryptoTypes.ts b/packages/taler-wallet-core/src/crypto/cryptoTypes.ts index 5351815a7..93a7cd1c4 100644 --- a/packages/taler-wallet-core/src/crypto/cryptoTypes.ts +++ b/packages/taler-wallet-core/src/crypto/cryptoTypes.ts @@ -157,7 +157,6 @@ export interface CreateRecoupReqRequest { denomPub: DenominationPubKey; denomPubHash: string; denomSig: UnblindedSignature; - recoupAmount: AmountJson; } /** @@ -170,5 +169,4 @@ export interface CreateRecoupRefreshReqRequest { denomPub: DenominationPubKey; denomPubHash: string; denomSig: UnblindedSignature; - recoupAmount: AmountJson; } diff --git a/packages/taler-wallet-core/src/crypto/workers/cryptoImplementation.ts b/packages/taler-wallet-core/src/crypto/workers/cryptoImplementation.ts index b366fa9ec..f9dcc6493 100644 --- a/packages/taler-wallet-core/src/crypto/workers/cryptoImplementation.ts +++ b/packages/taler-wallet-core/src/crypto/workers/cryptoImplementation.ts @@ -263,7 +263,6 @@ export class CryptoImplementation { const p = buildSigPS(TalerSignaturePurpose.WALLET_COIN_RECOUP) .put(decodeCrock(req.denomPubHash)) .put(decodeCrock(req.blindingKey)) - .put(amountToBuffer(Amounts.jsonifyAmount(req.recoupAmount))) .build(); const coinPriv = decodeCrock(req.coinPriv); @@ -274,7 +273,6 @@ export class CryptoImplementation { coin_sig: encodeCrock(coinSig), denom_pub_hash: req.denomPubHash, denom_sig: req.denomSig.rsa_signature, - amount: Amounts.stringify(req.recoupAmount), }; return paybackRequest; } else { @@ -283,7 +281,6 @@ export class CryptoImplementation { coin_sig: encodeCrock(coinSig), denom_pub_hash: req.denomPubHash, denom_sig: req.denomSig, - amount: Amounts.stringify(req.recoupAmount), }; return paybackRequest; } @@ -292,33 +289,32 @@ export class CryptoImplementation { /** * Create and sign a message to recoup a coin. */ - createRecoupRefreshRequest(req: CreateRecoupRefreshReqRequest): RecoupRefreshRequest { + createRecoupRefreshRequest( + req: CreateRecoupRefreshReqRequest, + ): RecoupRefreshRequest { const p = buildSigPS(TalerSignaturePurpose.WALLET_COIN_RECOUP_REFRESH) .put(decodeCrock(req.denomPubHash)) .put(decodeCrock(req.blindingKey)) - .put(amountToBuffer(Amounts.jsonifyAmount(req.recoupAmount))) .build(); const coinPriv = decodeCrock(req.coinPriv); const coinSig = eddsaSign(p, coinPriv); if (req.denomPub.cipher === DenomKeyType.LegacyRsa) { - const paybackRequest: RecoupRefreshRequest = { + const recoupRequest: RecoupRefreshRequest = { coin_blind_key_secret: req.blindingKey, coin_sig: encodeCrock(coinSig), denom_pub_hash: req.denomPubHash, denom_sig: req.denomSig.rsa_signature, - amount: Amounts.stringify(req.recoupAmount), }; - return paybackRequest; + return recoupRequest; } else { - const paybackRequest: RecoupRefreshRequest = { + const recoupRequest: RecoupRefreshRequest = { coin_blind_key_secret: req.blindingKey, coin_sig: encodeCrock(coinSig), denom_pub_hash: req.denomPubHash, denom_sig: req.denomSig, - amount: Amounts.stringify(req.recoupAmount), }; - return paybackRequest; + return recoupRequest; } } diff --git a/packages/taler-wallet-core/src/db.ts b/packages/taler-wallet-core/src/db.ts index 772061fb9..7f6b08e12 100644 --- a/packages/taler-wallet-core/src/db.ts +++ b/packages/taler-wallet-core/src/db.ts @@ -42,7 +42,6 @@ import { import { RetryInfo } from "./util/retries.js"; import { PayCoinSelection } from "./util/coinSelection.js"; import { Event, IDBDatabase } from "@gnu-taler/idb-bridge"; -import { PendingTaskInfo } from "./pending-types.js"; /** * Name of the Taler database. This is effectively the major @@ -140,7 +139,7 @@ export interface ReserveRecord { reservePriv: string; /** - * The exchange base URL. + * The exchange base URL for the reserve. */ exchangeBaseUrl: string; @@ -154,8 +153,6 @@ export interface ReserveRecord { */ timestampCreated: Timestamp; - operationStatus: OperationStatus; - /** * Time when the information about this reserve was posted to the bank. * @@ -206,13 +203,17 @@ export interface ReserveRecord { */ initialDenomSel: DenomSelectionState; + /** + * Current status of the reserve. + */ reserveStatus: ReserveRecordStatus; /** - * Was a reserve query requested? If so, query again instead - * of going into dormant status. + * Is there any work to be done for this reserve? + * + * FIXME: Technically redundant, since the reserveStatus would indicate this. */ - requestedQuery: boolean; + operationStatus: OperationStatus; /** * Time of the last successful status query. diff --git a/packages/taler-wallet-core/src/operations/backup/import.ts b/packages/taler-wallet-core/src/operations/backup/import.ts index 5ca1ebb9d..9f63441dd 100644 --- a/packages/taler-wallet-core/src/operations/backup/import.ts +++ b/packages/taler-wallet-core/src/operations/backup/import.ts @@ -457,7 +457,6 @@ export async function importBackup( exchangeBaseUrl: backupExchangeDetails.base_url, reservePub, reservePriv: backupReserve.reserve_priv, - requestedQuery: false, bankInfo, timestampCreated: backupReserve.timestamp_created, timestampBankConfirmed: diff --git a/packages/taler-wallet-core/src/operations/recoup.ts b/packages/taler-wallet-core/src/operations/recoup.ts index 559513d44..9ae045cfa 100644 --- a/packages/taler-wallet-core/src/operations/recoup.ts +++ b/packages/taler-wallet-core/src/operations/recoup.ts @@ -43,6 +43,7 @@ import { ReserveRecordStatus, WithdrawCoinSource, WalletStoresV1, + OperationStatus, } from "../db.js"; import { readSuccessResponseJsonOrThrow } from "../util/http.js"; @@ -186,7 +187,6 @@ async function recoupWithdrawCoin( denomPub: coin.denomPub, denomPubHash: coin.denomPubHash, denomSig: coin.denomSig, - recoupAmount: coin.currentAmount, }); const reqUrl = new URL(`/coins/${coin.coinPub}/recoup`, coin.exchangeBaseUrl); logger.trace(`requesting recoup via ${reqUrl.href}`); @@ -233,13 +233,9 @@ async function recoupWithdrawCoin( updatedCoin.status = CoinStatus.Dormant; const currency = updatedCoin.currentAmount.currency; updatedCoin.currentAmount = Amounts.getZero(currency); - if (updatedReserve.reserveStatus === ReserveRecordStatus.DORMANT) { - updatedReserve.reserveStatus = ReserveRecordStatus.QUERYING_STATUS; - updatedReserve.retryInfo = initRetryInfo(); - } else { - updatedReserve.requestedQuery = true; - updatedReserve.retryInfo = initRetryInfo(); - } + updatedReserve.reserveStatus = ReserveRecordStatus.QUERYING_STATUS; + updatedReserve.retryInfo = initRetryInfo(); + updatedReserve.operationStatus = OperationStatus.Pending; await tx.coins.put(updatedCoin); await tx.reserves.put(updatedReserve); await putGroupAsFinished(ws, tx, recoupGroup, coinIdx); @@ -268,9 +264,11 @@ async function recoupRefreshCoin( denomPub: coin.denomPub, denomPubHash: coin.denomPubHash, denomSig: coin.denomSig, - recoupAmount: coin.currentAmount, }); - const reqUrl = new URL(`/coins/${coin.coinPub}/recoup`, coin.exchangeBaseUrl); + const reqUrl = new URL( + `/coins/${coin.coinPub}/recoup-refresh`, + coin.exchangeBaseUrl, + ); logger.trace(`making recoup request for ${coin.coinPub}`); const resp = await ws.http.postJson(reqUrl.href, recoupRequest); @@ -381,7 +379,7 @@ async function processRecoupGroupImpl( } const ps = recoupGroup.coinPubs.map(async (x, i) => { try { - processRecoup(ws, recoupGroupId, i); + await processRecoup(ws, recoupGroupId, i); } catch (e) { logger.warn(`processRecoup failed: ${e}`); throw e; @@ -408,7 +406,7 @@ async function processRecoupGroupImpl( } for (const r of reserveSet.values()) { - processReserve(ws, r).catch((e) => { + processReserve(ws, r, true).catch((e) => { logger.error(`processing reserve ${r} after recoup failed`); }); } @@ -460,6 +458,9 @@ export async function createRecoupGroup( return recoupGroupId; } +/** + * Run the recoup protocol for a single coin in a recoup group. + */ async function processRecoup( ws: InternalWalletState, recoupGroupId: string, @@ -486,7 +487,7 @@ async function processRecoup( const coin = await tx.coins.get(coinPub); if (!coin) { - throw Error(`Coin ${coinPub} not found, can't request payback`); + throw Error(`Coin ${coinPub} not found, can't request recoup`); } return coin; }); diff --git a/packages/taler-wallet-core/src/operations/reserves.ts b/packages/taler-wallet-core/src/operations/reserves.ts index 1550d946b..7d7b26aba 100644 --- a/packages/taler-wallet-core/src/operations/reserves.ts +++ b/packages/taler-wallet-core/src/operations/reserves.ts @@ -155,7 +155,6 @@ export async function createReserve( retryInfo: initRetryInfo(), lastError: undefined, currency: req.amount.currency, - requestedQuery: false, operationStatus: OperationStatus.Pending, }; @@ -255,7 +254,6 @@ export async function forceQueryReserve( reserve.operationStatus = OperationStatus.Pending; break; default: - reserve.requestedQuery = true; break; } reserve.retryInfo = initRetryInfo(); diff --git a/packages/taler-wallet-core/src/util/http.ts b/packages/taler-wallet-core/src/util/http.ts index 0556d2274..3a7062c99 100644 --- a/packages/taler-wallet-core/src/util/http.ts +++ b/packages/taler-wallet-core/src/util/http.ts @@ -164,7 +164,7 @@ export async function readUnexpectedResponseDetails( } return makeErrorDetails( TalerErrorCode.WALLET_UNEXPECTED_REQUEST_ERROR, - "Unexpected error code in response", + `Unexpected HTTP status (${httpResponse.status}) in response`, { requestUrl: httpResponse.requestUrl, httpStatusCode: httpResponse.status, @@ -220,7 +220,7 @@ export function throwUnexpectedRequestError( throw new OperationFailedError( makeErrorDetails( TalerErrorCode.WALLET_UNEXPECTED_REQUEST_ERROR, - "Unexpected error code in response", + `Unexpected HTTP status ${httpResponse.status} in response`, { requestUrl: httpResponse.requestUrl, httpStatusCode: httpResponse.status, -- cgit v1.2.3