[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[taler-wallet-core] branch master updated: prevent conflicting coin allo
From: |
gnunet |
Subject: |
[taler-wallet-core] branch master updated: prevent conflicting coin allocation with concurrent payments |
Date: |
Tue, 22 Jun 2021 18:43:17 +0200 |
This is an automated email from the git hooks/post-receive script.
dold pushed a commit to branch master
in repository wallet-core.
The following commit(s) were added to refs/heads/master by this push:
new 09d1dd83 prevent conflicting coin allocation with concurrent payments
09d1dd83 is described below
commit 09d1dd83ec1bf9ca16841d0afb18b9a7da705bcb
Author: Florian Dold <florian@dold.me>
AuthorDate: Tue Jun 22 18:43:11 2021 +0200
prevent conflicting coin allocation with concurrent payments
---
packages/taler-wallet-core/src/db.ts | 13 +++++++++
.../taler-wallet-core/src/operations/deposits.ts | 12 ++++++--
packages/taler-wallet-core/src/operations/pay.ts | 33 ++++++++++++++--------
3 files changed, 44 insertions(+), 14 deletions(-)
diff --git a/packages/taler-wallet-core/src/db.ts
b/packages/taler-wallet-core/src/db.ts
index 2d2c0615..36b4e086 100644
--- a/packages/taler-wallet-core/src/db.ts
+++ b/packages/taler-wallet-core/src/db.ts
@@ -848,6 +848,17 @@ export interface CoinRecord {
* Status of the coin.
*/
status: CoinStatus;
+
+ /**
+ * Information about what the coin has been allocated for.
+ * Used to prevent allocation of the same coin for two different payments.
+ */
+ allocation?: CoinAllocation;
+}
+
+export interface CoinAllocation {
+ id: string;
+ amount: AmountString;
}
export enum ProposalStatus {
@@ -1643,6 +1654,8 @@ export interface DepositGroupRecord {
payCoinSelection: PayCoinSelection;
+ payCoinSelectionUid: string;
+
totalPayCost: AmountJson;
effectiveDepositAmount: AmountJson;
diff --git a/packages/taler-wallet-core/src/operations/deposits.ts
b/packages/taler-wallet-core/src/operations/deposits.ts
index 9dee7557..c788a9ea 100644
--- a/packages/taler-wallet-core/src/operations/deposits.ts
+++ b/packages/taler-wallet-core/src/operations/deposits.ts
@@ -36,7 +36,7 @@ import {
timestampTruncateToSecond,
TrackDepositGroupRequest,
TrackDepositGroupResponse,
- URL
+ URL,
} from "@gnu-taler/taler-util";
import { InternalWalletState } from "../common.js";
import { kdf } from "../crypto/primitives/kdf.js";
@@ -433,7 +433,8 @@ export async function createDepositGroup(
timestampCreated: timestamp,
timestampFinished: undefined,
payCoinSelection: payCoinSel,
- depositedPerCoin: payCoinSel.coinPubs.map((x) => false),
+ payCoinSelectionUid: encodeCrock(getRandomBytes(32)),
+ depositedPerCoin: payCoinSel.coinPubs.map(() => false),
merchantPriv: merchantPair.priv,
merchantPub: merchantPair.pub,
totalPayCost: totalDepositCost,
@@ -454,7 +455,12 @@ export async function createDepositGroup(
denominations: x.denominations,
}))
.runReadWrite(async (tx) => {
- await applyCoinSpend(ws, tx, payCoinSel);
+ await applyCoinSpend(
+ ws,
+ tx,
+ payCoinSel,
+ `deposit-group:${depositGroup.depositGroupId}`,
+ );
await tx.depositGroups.put(depositGroup);
});
diff --git a/packages/taler-wallet-core/src/operations/pay.ts
b/packages/taler-wallet-core/src/operations/pay.ts
index 71f11c96..280586c3 100644
--- a/packages/taler-wallet-core/src/operations/pay.ts
+++ b/packages/taler-wallet-core/src/operations/pay.ts
@@ -385,24 +385,34 @@ export async function applyCoinSpend(
denominations: typeof WalletStoresV1.denominations;
}>,
coinSelection: PayCoinSelection,
+ allocationId: string,
) {
for (let i = 0; i < coinSelection.coinPubs.length; i++) {
const coin = await tx.coins.get(coinSelection.coinPubs[i]);
if (!coin) {
throw Error("coin allocated for payment doesn't exist anymore");
}
+ const contrib = coinSelection.coinContributions[i];
if (coin.status !== CoinStatus.Fresh) {
- // applyCoinSpend was called again, probably
- // because of a coin re-selection to recover after
- // accidental double spending.
- // Ignore coins we already marked as spent.
- continue;
+ const alloc = coin.allocation;
+ if (!alloc) {
+ continue;
+ }
+ if (alloc.id !== allocationId) {
+ // FIXME: assign error code
+ throw Error("conflicting coin allocation (id)");
+ }
+ if (0 !== Amounts.cmp(alloc.amount, contrib)) {
+ // FIXME: assign error code
+ throw Error("conflicting coin allocation (contrib)");
+ }
}
coin.status = CoinStatus.Dormant;
- const remaining = Amounts.sub(
- coin.currentAmount,
- coinSelection.coinContributions[i],
- );
+ coin.allocation = {
+ id: allocationId,
+ amount: Amounts.stringify(contrib),
+ };
+ const remaining = Amounts.sub(coin.currentAmount, contrib);
if (remaining.saturated) {
throw Error("not enough remaining balance on coin for payment");
}
@@ -482,7 +492,7 @@ async function recordConfirmPay(
await tx.proposals.put(p);
}
await tx.purchases.put(t);
- await applyCoinSpend(ws, tx, coinSelection);
+ await applyCoinSpend(ws, tx, coinSelection, `proposal:${t.proposalId}`);
});
ws.notify({
@@ -1082,9 +1092,10 @@ async function handleInsufficientFunds(
return;
}
p.payCoinSelection = res;
+ p.payCoinSelectionUid = encodeCrock(getRandomBytes(32));
p.coinDepositPermissions = undefined;
await tx.purchases.put(p);
- await applyCoinSpend(ws, tx, res);
+ await applyCoinSpend(ws, tx, res, `proposal:${p.proposalId}`);
});
}
--
To stop receiving notification emails like this one, please contact
gnunet@gnunet.org.
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- [taler-wallet-core] branch master updated: prevent conflicting coin allocation with concurrent payments,
gnunet <=