aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFlorian Dold <florian@dold.me>2022-01-12 15:51:56 +0100
committerFlorian Dold <florian@dold.me>2022-01-12 15:51:56 +0100
commitdc596f1f4d494c3bf9e57253d773205dc0479179 (patch)
tree9c5dc7e51a9c21582819be6ad1779937a8d71378
parentdbdad96b27619b8190571b899d3b11dd6af39335 (diff)
implement latest recoup protocol
-rw-r--r--packages/taler-util/src/talerTypes.ts10
-rw-r--r--packages/taler-wallet-core/src/crypto/cryptoTypes.ts2
-rw-r--r--packages/taler-wallet-core/src/crypto/workers/cryptoImplementation.ts18
-rw-r--r--packages/taler-wallet-core/src/db.ts15
-rw-r--r--packages/taler-wallet-core/src/operations/backup/import.ts1
-rw-r--r--packages/taler-wallet-core/src/operations/recoup.ts27
-rw-r--r--packages/taler-wallet-core/src/operations/reserves.ts2
-rw-r--r--packages/taler-wallet-core/src/util/http.ts4
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,