diff options
author | Florian Dold <florian@dold.me> | 2022-03-10 16:30:24 +0100 |
---|---|---|
committer | Florian Dold <florian@dold.me> | 2022-03-10 16:30:24 +0100 |
commit | 9d660788521d93452aa767d86158889fd4870fd1 (patch) | |
tree | 1ee3315e9224ee56b1848cfab02974a2dc6a2da6 /packages/taler-wallet-core/src/operations | |
parent | 1607c728bca19a003ca08b64b4d2afc73e4d1e2a (diff) | |
download | wallet-core-9d660788521d93452aa767d86158889fd4870fd1.tar.xz |
wallet-core: do not rely on reserve history for withdrawals
Diffstat (limited to 'packages/taler-wallet-core/src/operations')
7 files changed, 99 insertions, 77 deletions
diff --git a/packages/taler-wallet-core/src/operations/backup/import.ts b/packages/taler-wallet-core/src/operations/backup/import.ts index 84acfb16c..35b62c2e4 100644 --- a/packages/taler-wallet-core/src/operations/backup/import.ts +++ b/packages/taler-wallet-core/src/operations/backup/import.ts @@ -419,7 +419,6 @@ export async function importBackup( coinPub: compCoin.coinPub, suspended: false, exchangeBaseUrl: backupExchangeDetails.base_url, - denomPub: backupDenomination.denom_pub, denomPubHash, status: backupCoin.fresh ? CoinStatus.Fresh diff --git a/packages/taler-wallet-core/src/operations/pay.ts b/packages/taler-wallet-core/src/operations/pay.ts index 97d87e5cc..6001cac4f 100644 --- a/packages/taler-wallet-core/src/operations/pay.ts +++ b/packages/taler-wallet-core/src/operations/pay.ts @@ -315,7 +315,7 @@ export async function getCandidatePayCoins( candidateCoins.push({ availableAmount: coin.currentAmount, coinPub: coin.coinPub, - denomPub: coin.denomPub, + denomPub: denom.denomPub, feeDeposit: denom.feeDeposit, exchangeBaseUrl: denom.exchangeBaseUrl, }); @@ -1397,7 +1397,7 @@ export async function generateDepositPermissions( coinPub: coin.coinPub, contractTermsHash: contractData.contractTermsHash, denomPubHash: coin.denomPubHash, - denomKeyType: coin.denomPub.cipher, + denomKeyType: denom.denomPub.cipher, denomSig: coin.denomSig, exchangeBaseUrl: coin.exchangeBaseUrl, feeDeposit: denom.feeDeposit, diff --git a/packages/taler-wallet-core/src/operations/recoup.ts b/packages/taler-wallet-core/src/operations/recoup.ts index afca923bd..23d14f212 100644 --- a/packages/taler-wallet-core/src/operations/recoup.ts +++ b/packages/taler-wallet-core/src/operations/recoup.ts @@ -164,18 +164,34 @@ async function recoupWithdrawCoin( cs: WithdrawCoinSource, ): Promise<void> { const reservePub = cs.reservePub; - const reserve = await ws.db + const d = await ws.db .mktx((x) => ({ reserves: x.reserves, + denominations: x.denominations, })) .runReadOnly(async (tx) => { - return tx.reserves.get(reservePub); + const reserve = await tx.reserves.get(reservePub); + if (!reserve) { + return; + } + const denomInfo = await ws.getDenomInfo( + ws, + tx, + reserve.exchangeBaseUrl, + coin.denomPubHash, + ); + if (!denomInfo) { + return; + } + return { reserve, denomInfo }; }); - if (!reserve) { + if (!d) { // FIXME: We should at least emit some pending operation / warning for this? return; } + const { reserve, denomInfo } = d; + ws.notify({ type: NotificationType.RecoupStarted, }); @@ -184,7 +200,7 @@ async function recoupWithdrawCoin( blindingKey: coin.blindingKey, coinPriv: coin.coinPriv, coinPub: coin.coinPub, - denomPub: coin.denomPub, + denomPub: denomInfo.denomPub, denomPubHash: coin.denomPubHash, denomSig: coin.denomSig, }); @@ -253,6 +269,28 @@ async function recoupRefreshCoin( coin: CoinRecord, cs: RefreshCoinSource, ): Promise<void> { + const d = await ws.db + .mktx((x) => ({ + coins: x.coins, + denominations: x.denominations, + })) + .runReadOnly(async (tx) => { + const denomInfo = await ws.getDenomInfo( + ws, + tx, + coin.exchangeBaseUrl, + coin.denomPubHash, + ); + if (!denomInfo) { + return; + } + return { denomInfo }; + }); + if (!d) { + // FIXME: We should at least emit some pending operation / warning for this? + return; + } + ws.notify({ type: NotificationType.RecoupStarted, }); @@ -261,7 +299,7 @@ async function recoupRefreshCoin( blindingKey: coin.blindingKey, coinPriv: coin.coinPriv, coinPub: coin.coinPub, - denomPub: coin.denomPub, + denomPub: d.denomInfo.denomPub, denomPubHash: coin.denomPubHash, denomSig: coin.denomSig, }); diff --git a/packages/taler-wallet-core/src/operations/refresh.ts b/packages/taler-wallet-core/src/operations/refresh.ts index ba4cb697d..550119de1 100644 --- a/packages/taler-wallet-core/src/operations/refresh.ts +++ b/packages/taler-wallet-core/src/operations/refresh.ts @@ -395,7 +395,7 @@ async function refreshMelt( oldCoin.exchangeBaseUrl, ); let meltReqBody: any; - if (oldCoin.denomPub.cipher === DenomKeyType.Rsa) { + if (oldDenom.denomPub.cipher === DenomKeyType.Rsa) { meltReqBody = { coin_pub: oldCoin.coinPub, confirm_sig: derived.confirmSig, @@ -671,7 +671,6 @@ async function refreshReveal( coinPriv: pc.coinPriv, coinPub: pc.coinPub, currentAmount: denom.value, - denomPub: denom.denomPub, denomPubHash: denom.denomPubHash, denomSig: { cipher: DenomKeyType.Rsa, diff --git a/packages/taler-wallet-core/src/operations/reserves.ts b/packages/taler-wallet-core/src/operations/reserves.ts index 7011b2f26..a16d3ec31 100644 --- a/packages/taler-wallet-core/src/operations/reserves.ts +++ b/packages/taler-wallet-core/src/operations/reserves.ts @@ -587,8 +587,8 @@ async function updateReserve( logger.trace(`got reserve status ${j2s(result.response)}`); const reserveInfo = result.response; - const balance = Amounts.parseOrThrow(reserveInfo.balance); - const currency = balance.currency; + const reserveBalance = Amounts.parseOrThrow(reserveInfo.balance); + const currency = reserveBalance.currency; await updateWithdrawalDenoms(ws, reserve.exchangeBaseUrl); const denoms = await getCandidateWithdrawalDenoms( @@ -598,73 +598,50 @@ async function updateReserve( const newWithdrawalGroup = await ws.db .mktx((x) => ({ - coins: x.coins, planchets: x.planchets, withdrawalGroups: x.withdrawalGroups, reserves: x.reserves, + denominations: x.denominations, })) .runReadWrite(async (tx) => { const newReserve = await tx.reserves.get(reserve.reservePub); if (!newReserve) { return; } - let amountReservePlus = Amounts.getZero(currency); + let amountReservePlus = reserveBalance; let amountReserveMinus = Amounts.getZero(currency); - // Subtract withdrawal groups for this reserve from the available amount. + // Subtract amount allocated in unfinished withdrawal groups + // for this reserve from the available amount. await tx.withdrawalGroups.indexes.byReservePub .iter(reservePub) - .forEach((wg) => { - const cost = wg.denomsSel.totalWithdrawCost; - amountReserveMinus = Amounts.add(amountReserveMinus, cost).amount; - }); - - for (const entry of reserveInfo.history) { - switch (entry.type) { - case ReserveTransactionType.Credit: - amountReservePlus = Amounts.add( - amountReservePlus, - Amounts.parseOrThrow(entry.amount), - ).amount; - break; - case ReserveTransactionType.Recoup: - amountReservePlus = Amounts.add( - amountReservePlus, - Amounts.parseOrThrow(entry.amount), - ).amount; - break; - case ReserveTransactionType.Closing: - amountReserveMinus = Amounts.add( - amountReserveMinus, - Amounts.parseOrThrow(entry.amount), - ).amount; - break; - case ReserveTransactionType.Withdraw: { - // Now we check if the withdrawal transaction - // is part of any withdrawal known to this wallet. - const planchet = await tx.planchets.indexes.byCoinEvHash.get( - entry.h_coin_envelope, - ); - if (planchet) { - // Amount is already accounted in some withdrawal session - break; - } - const coin = await tx.coins.indexes.byCoinEvHash.get( - entry.h_coin_envelope, - ); - if (coin) { - // Amount is already accounted in some withdrawal session - break; - } - // Amount has been claimed by some withdrawal we don't know about - amountReserveMinus = Amounts.add( - amountReserveMinus, - Amounts.parseOrThrow(entry.amount), - ).amount; - break; + .forEachAsync(async (wg) => { + if (wg.timestampFinish) { + return; } - } - } + await tx.planchets.indexes.byGroup + .iter(wg.withdrawalGroupId) + .forEachAsync(async (pr) => { + if (pr.withdrawalDone) { + return; + } + const denomInfo = await ws.getDenomInfo( + ws, + tx, + wg.exchangeBaseUrl, + pr.denomPubHash, + ); + if (!denomInfo) { + logger.error(`no denom info found for ${pr.denomPubHash}`); + return; + } + amountReserveMinus = Amounts.add( + amountReserveMinus, + denomInfo.value, + denomInfo.feeWithdraw, + ).amount; + }); + }); const remainingAmount = Amounts.sub( amountReservePlus, diff --git a/packages/taler-wallet-core/src/operations/tip.ts b/packages/taler-wallet-core/src/operations/tip.ts index cc2d71ef4..a2a4e6f49 100644 --- a/packages/taler-wallet-core/src/operations/tip.ts +++ b/packages/taler-wallet-core/src/operations/tip.ts @@ -374,7 +374,6 @@ async function processTipImpl( walletTipId: walletTipId, }, currentAmount: denom.value, - denomPub: denom.denomPub, denomPubHash: denom.denomPubHash, denomSig: { cipher: DenomKeyType.Rsa, rsa_signature: denomSigRsa }, exchangeBaseUrl: tipRecord.exchangeBaseUrl, diff --git a/packages/taler-wallet-core/src/operations/withdraw.ts b/packages/taler-wallet-core/src/operations/withdraw.ts index 731e9b3aa..ae3763a02 100644 --- a/packages/taler-wallet-core/src/operations/withdraw.ts +++ b/packages/taler-wallet-core/src/operations/withdraw.ts @@ -418,10 +418,7 @@ async function processPlanchetGenerate( coinIdx, coinPriv: r.coinPriv, coinPub: r.coinPub, - coinValue: r.coinValue, - denomPub: r.denomPub, denomPubHash: r.denomPubHash, - isFromTip: false, reservePub: r.reservePub, withdrawalDone: false, withdrawSig: r.withdrawSig, @@ -557,6 +554,7 @@ async function processPlanchetVerifyAndStoreCoin( .mktx((x) => ({ withdrawalGroups: x.withdrawalGroups, planchets: x.planchets, + denominations: x.denominations, })) .runReadOnly(async (tx) => { let planchet = await tx.planchets.indexes.byGroupAndIndex.get([ @@ -570,16 +568,29 @@ async function processPlanchetVerifyAndStoreCoin( logger.warn("processPlanchet: planchet already withdrawn"); return; } - return { planchet, exchangeBaseUrl: withdrawalGroup.exchangeBaseUrl }; + const denomInfo = await ws.getDenomInfo( + ws, + tx, + withdrawalGroup.exchangeBaseUrl, + planchet.denomPubHash, + ); + if (!denomInfo) { + return; + } + return { + planchet, + denomInfo, + exchangeBaseUrl: withdrawalGroup.exchangeBaseUrl, + }; }); if (!d) { return; } - const { planchet, exchangeBaseUrl } = d; + const { planchet, denomInfo } = d; - const planchetDenomPub = planchet.denomPub; + const planchetDenomPub = denomInfo.denomPub; if (planchetDenomPub.cipher !== DenomKeyType.Rsa) { throw Error(`cipher (${planchetDenomPub.cipher}) not supported`); } @@ -623,9 +634,9 @@ async function processPlanchetVerifyAndStoreCoin( } let denomSig: UnblindedSignature; - if (planchet.denomPub.cipher === DenomKeyType.Rsa) { + if (planchetDenomPub.cipher === DenomKeyType.Rsa) { denomSig = { - cipher: planchet.denomPub.cipher, + cipher: planchetDenomPub.cipher, rsa_signature: denomSigRsa, }; } else { @@ -636,12 +647,11 @@ async function processPlanchetVerifyAndStoreCoin( blindingKey: planchet.blindingKey, coinPriv: planchet.coinPriv, coinPub: planchet.coinPub, - currentAmount: planchet.coinValue, - denomPub: planchet.denomPub, + currentAmount: denomInfo.value, denomPubHash: planchet.denomPubHash, denomSig, coinEvHash: planchet.coinEvHash, - exchangeBaseUrl: exchangeBaseUrl, + exchangeBaseUrl: d.exchangeBaseUrl, status: CoinStatus.Fresh, coinSource: { type: CoinSourceType.Withdraw, |