aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFlorian Dold <florian@dold.me>2022-11-02 13:40:03 +0100
committerFlorian Dold <florian@dold.me>2022-11-02 13:40:03 +0100
commitfe011321a4b65bc0736634ee2a4d9c7bf0618351 (patch)
tree5bf2b5b3eff072390c0a857431b1212fd6d134f2
parent87bc4a6fcd3b274f25ffe9a74196aa5f4f586b7e (diff)
downloadwallet-core-fe011321a4b65bc0736634ee2a4d9c7bf0618351.tar.xz
wallet-core: compute residual amount for recoup properly
-rw-r--r--packages/taler-util/src/backup-types.ts2
-rw-r--r--packages/taler-wallet-cli/src/integrationtests/test-revocation.ts1
-rw-r--r--packages/taler-wallet-core/src/db.ts1
-rw-r--r--packages/taler-wallet-core/src/operations/backup/export.ts1
-rw-r--r--packages/taler-wallet-core/src/operations/backup/import.ts1
-rw-r--r--packages/taler-wallet-core/src/operations/recoup.ts20
-rw-r--r--packages/taler-wallet-core/src/operations/refresh.ts13
7 files changed, 30 insertions, 9 deletions
diff --git a/packages/taler-util/src/backup-types.ts b/packages/taler-util/src/backup-types.ts
index 71f5bd04e..b3c6b5515 100644
--- a/packages/taler-util/src/backup-types.ts
+++ b/packages/taler-util/src/backup-types.ts
@@ -534,6 +534,8 @@ export interface BackupRefreshCoinSource {
* Public key of the coin that was refreshed into this coin.
*/
old_coin_pub: string;
+
+ refresh_group_id: string;
}
/**
diff --git a/packages/taler-wallet-cli/src/integrationtests/test-revocation.ts b/packages/taler-wallet-cli/src/integrationtests/test-revocation.ts
index 3ed071a18..0fbb4960e 100644
--- a/packages/taler-wallet-cli/src/integrationtests/test-revocation.ts
+++ b/packages/taler-wallet-cli/src/integrationtests/test-revocation.ts
@@ -181,6 +181,7 @@ export async function runRevocationTest(t: GlobalTestState) {
await makeTestPayment(t, { wallet, merchant, order });
wallet.deleteDatabase();
+
await withdrawViaBank(t, { wallet, bank, exchange, amount: "TESTKUDOS:15" });
const coinDump = await wallet.client.call(WalletApiOperation.DumpCoins, {});
diff --git a/packages/taler-wallet-core/src/db.ts b/packages/taler-wallet-core/src/db.ts
index 307f76f21..dcc9fbe99 100644
--- a/packages/taler-wallet-core/src/db.ts
+++ b/packages/taler-wallet-core/src/db.ts
@@ -640,6 +640,7 @@ export interface WithdrawCoinSource {
export interface RefreshCoinSource {
type: CoinSourceType.Refresh;
+ refreshGroupId: string;
oldCoinPub: string;
}
diff --git a/packages/taler-wallet-core/src/operations/backup/export.ts b/packages/taler-wallet-core/src/operations/backup/export.ts
index b33d2f11a..965d51776 100644
--- a/packages/taler-wallet-core/src/operations/backup/export.ts
+++ b/packages/taler-wallet-core/src/operations/backup/export.ts
@@ -240,6 +240,7 @@ export async function exportBackup(
bcs = {
type: BackupCoinSourceType.Refresh,
old_coin_pub: coin.coinSource.oldCoinPub,
+ refresh_group_id: coin.coinSource.refreshGroupId,
};
break;
case CoinSourceType.Tip:
diff --git a/packages/taler-wallet-core/src/operations/backup/import.ts b/packages/taler-wallet-core/src/operations/backup/import.ts
index 73ad1ecc6..133699647 100644
--- a/packages/taler-wallet-core/src/operations/backup/import.ts
+++ b/packages/taler-wallet-core/src/operations/backup/import.ts
@@ -250,6 +250,7 @@ export async function importCoin(
coinSource = {
type: CoinSourceType.Refresh,
oldCoinPub: backupCoin.coin_source.old_coin_pub,
+ refreshGroupId: backupCoin.coin_source.refresh_group_id,
};
break;
case BackupCoinSourceType.Tip:
diff --git a/packages/taler-wallet-core/src/operations/recoup.ts b/packages/taler-wallet-core/src/operations/recoup.ts
index f16225295..c2df6115b 100644
--- a/packages/taler-wallet-core/src/operations/recoup.ts
+++ b/packages/taler-wallet-core/src/operations/recoup.ts
@@ -279,11 +279,21 @@ async function recoupRefreshCoin(
checkDbInvariant(!!oldCoinDenom);
checkDbInvariant(!!revokedCoinDenom);
revokedCoin.status = CoinStatus.Dormant;
- recoupGroup.scheduleRefreshCoins.push({
- coinPub: oldCoin.coinPub,
- //amount: Amounts.sub(oldCoinDenom.value, revokedCoinDenom.value).amount,
- amount: revokedCoinDenom.value,
- });
+ if (!revokedCoin.spendAllocation) {
+ // We don't know what happened to this coin
+ logger.error(
+ `can't refresh-recoup coin ${revokedCoin.coinPub}, no spendAllocation known`,
+ );
+ } else {
+ let residualAmount = Amounts.sub(
+ revokedCoinDenom.value,
+ revokedCoin.spendAllocation.amount,
+ ).amount;
+ recoupGroup.scheduleRefreshCoins.push({
+ coinPub: oldCoin.coinPub,
+ amount: residualAmount,
+ });
+ }
await tx.coins.put(revokedCoin);
await tx.coins.put(oldCoin);
await putGroupAsFinished(ws, tx, recoupGroup, coinIdx);
diff --git a/packages/taler-wallet-core/src/operations/refresh.ts b/packages/taler-wallet-core/src/operations/refresh.ts
index e18faea32..ea0fae8bb 100644
--- a/packages/taler-wallet-core/src/operations/refresh.ts
+++ b/packages/taler-wallet-core/src/operations/refresh.ts
@@ -687,6 +687,7 @@ async function refreshReveal(
status: CoinStatus.Fresh,
coinSource: {
type: CoinSourceType.Refresh,
+ refreshGroupId,
oldCoinPub: refreshGroup.oldCoinPubs[coinIndex],
},
coinEvHash: pc.coinEvHash,
@@ -838,10 +839,6 @@ async function processRefreshSession(
* Refreshes the remaining amount on the coin, effectively capturing the remaining
* value in the refresh group.
*
- * The caller must ensure that
- * the remaining amount was updated correctly before the coin was deposited or
- * credited.
- *
* The caller must also ensure that the coins that should be refreshed exist
* in the current database transaction.
*/
@@ -893,6 +890,10 @@ export async function createRefreshGroup(
);
switch (coin.status) {
case CoinStatus.Dormant:
+ coin.spendAllocation = {
+ amount: Amounts.stringify(ocp.amount),
+ id: `txn:refresh:${refreshGroupId}`,
+ };
break;
case CoinStatus.Fresh: {
coin.status = CoinStatus.Dormant;
@@ -911,6 +912,10 @@ export async function createRefreshGroup(
// For suspended coins, we don't have to adjust coin
// availability, as they are not counted as available.
coin.status = CoinStatus.Dormant;
+ coin.spendAllocation = {
+ amount: Amounts.stringify(ocp.amount),
+ id: `txn:refresh:${refreshGroupId}`,
+ };
break;
}
default: