diff options
Diffstat (limited to 'packages')
-rw-r--r-- | packages/taler-wallet-core/src/coinSelection.ts | 4 | ||||
-rw-r--r-- | packages/taler-wallet-core/src/common.ts | 4 | ||||
-rw-r--r-- | packages/taler-wallet-core/src/deposits.ts | 6 | ||||
-rw-r--r-- | packages/taler-wallet-core/src/pay-merchant.ts | 8 | ||||
-rw-r--r-- | packages/taler-wallet-core/src/pay-peer-common.ts | 6 | ||||
-rw-r--r-- | packages/taler-wallet-core/src/recoup.ts | 85 | ||||
-rw-r--r-- | packages/taler-wallet-core/src/refresh.ts | 22 | ||||
-rw-r--r-- | packages/taler-wallet-core/src/wallet.ts | 40 | ||||
-rw-r--r-- | packages/taler-wallet-core/src/withdraw.ts | 15 |
9 files changed, 61 insertions, 129 deletions
diff --git a/packages/taler-wallet-core/src/coinSelection.ts b/packages/taler-wallet-core/src/coinSelection.ts index f0b435b54..e1ae613bc 100644 --- a/packages/taler-wallet-core/src/coinSelection.ts +++ b/packages/taler-wallet-core/src/coinSelection.ts @@ -64,7 +64,7 @@ import { getAutoRefreshExecuteThreshold } from "./common.js"; import { DenominationRecord, WalletDbReadOnlyTransaction } from "./db.js"; import { isWithdrawableDenom } from "./denominations.js"; import { getExchangeWireDetailsInTx } from "./exchanges.js"; -import { InternalWalletState } from "./wallet.js"; +import { getDenomInfo, InternalWalletState } from "./wallet.js"; const logger = new Logger("coinSelection.ts"); @@ -1088,7 +1088,7 @@ export async function selectPeerCoins( if (!coin) { throw Error("repair not possible, coin not found"); } - const denom = await ws.getDenomInfo( + const denom = await getDenomInfo( ws, tx, coin.exchangeBaseUrl, diff --git a/packages/taler-wallet-core/src/common.ts b/packages/taler-wallet-core/src/common.ts index 8c6650f4a..08adb2515 100644 --- a/packages/taler-wallet-core/src/common.ts +++ b/packages/taler-wallet-core/src/common.ts @@ -61,7 +61,7 @@ import { timestampPreciseToDb, } from "./db.js"; import { createRefreshGroup } from "./refresh.js"; -import { InternalWalletState } from "./wallet.js"; +import { InternalWalletState, getDenomInfo } from "./wallet.js"; const logger = new Logger("operations/common.ts"); @@ -161,7 +161,7 @@ export async function spendCoins( if (!coin) { throw Error("coin allocated for payment doesn't exist anymore"); } - const denom = await ws.getDenomInfo( + const denom = await getDenomInfo( ws, tx, coin.exchangeBaseUrl, diff --git a/packages/taler-wallet-core/src/deposits.ts b/packages/taler-wallet-core/src/deposits.ts index ed8778368..9db8cfc27 100644 --- a/packages/taler-wallet-core/src/deposits.ts +++ b/packages/taler-wallet-core/src/deposits.ts @@ -109,7 +109,7 @@ import { notifyTransition, parseTransactionIdentifier, } from "./transactions.js"; -import { InternalWalletState } from "./wallet.js"; +import { InternalWalletState, getDenomInfo } from "./wallet.js"; import { getCandidateWithdrawalDenomsTx } from "./withdraw.js"; /** @@ -1527,7 +1527,7 @@ export async function getCounterpartyEffectiveDepositAmount( if (!coin) { throw Error("can't calculate deposit amount, coin not found"); } - const denom = await ws.getDenomInfo( + const denom = await getDenomInfo( ws, tx, coin.exchangeBaseUrl, @@ -1593,7 +1593,7 @@ async function getTotalFeesForDepositAmount( if (!coin) { throw Error("can't calculate deposit amount, coin not found"); } - const denom = await ws.getDenomInfo( + const denom = await getDenomInfo( ws, tx, coin.exchangeBaseUrl, diff --git a/packages/taler-wallet-core/src/pay-merchant.ts b/packages/taler-wallet-core/src/pay-merchant.ts index 8fcb728d4..332660ad5 100644 --- a/packages/taler-wallet-core/src/pay-merchant.ts +++ b/packages/taler-wallet-core/src/pay-merchant.ts @@ -138,7 +138,11 @@ import { notifyTransition, parseTransactionIdentifier, } from "./transactions.js"; -import { EXCHANGE_COINS_LOCK, InternalWalletState } from "./wallet.js"; +import { + EXCHANGE_COINS_LOCK, + getDenomInfo, + InternalWalletState, +} from "./wallet.js"; import { getCandidateWithdrawalDenomsTx } from "./withdraw.js"; /** @@ -2959,7 +2963,7 @@ async function computeRefreshRequest( if (!coin) { throw Error("coin not found"); } - const denomInfo = await ws.getDenomInfo( + const denomInfo = await getDenomInfo( ws, tx, coin.exchangeBaseUrl, diff --git a/packages/taler-wallet-core/src/pay-peer-common.ts b/packages/taler-wallet-core/src/pay-peer-common.ts index efb5bdb7e..dbc3376b4 100644 --- a/packages/taler-wallet-core/src/pay-peer-common.ts +++ b/packages/taler-wallet-core/src/pay-peer-common.ts @@ -33,7 +33,7 @@ import type { SelectedPeerCoin } from "./coinSelection.js"; import { SpendCoinDetails } from "./crypto/cryptoImplementation.js"; import { PeerPushPaymentCoinSelection, ReserveRecord } from "./db.js"; import { getTotalRefreshCost } from "./refresh.js"; -import { InternalWalletState } from "./wallet.js"; +import { InternalWalletState, getDenomInfo } from "./wallet.js"; import { getCandidateWithdrawalDenomsTx } from "./withdraw.js"; /** @@ -50,7 +50,7 @@ export async function queryCoinInfosForSelection( if (!coin) { throw Error("coin not found anymore"); } - const denom = await ws.getDenomInfo( + const denom = await getDenomInfo( ws, tx, coin.exchangeBaseUrl, @@ -84,7 +84,7 @@ export async function getTotalPeerPaymentCost( if (!coin) { throw Error("can't calculate payment cost, coin not found"); } - const denomInfo = await ws.getDenomInfo( + const denomInfo = await getDenomInfo( ws, tx, coin.exchangeBaseUrl, diff --git a/packages/taler-wallet-core/src/recoup.ts b/packages/taler-wallet-core/src/recoup.ts index 0ec71f4e7..3105b3709 100644 --- a/packages/taler-wallet-core/src/recoup.ts +++ b/packages/taler-wallet-core/src/recoup.ts @@ -39,7 +39,6 @@ import { codecForReserveStatus, encodeCrock, getRandomBytes, - j2s, } from "@gnu-taler/taler-util"; import { readSuccessResponseJsonOrThrow } from "@gnu-taler/taler-util/http"; import { @@ -56,23 +55,23 @@ import { RecoupOperationStatus, RefreshCoinSource, WalletDbReadWriteTransaction, - WithdrawCoinSource, WithdrawalGroupStatus, WithdrawalRecordType, timestampPreciseToDb, } from "./db.js"; +import { recoupWithdrawCoin } from "./recoupWithdrawCoin.js"; import { createRefreshGroup } from "./refresh.js"; import { constructTransactionIdentifier } from "./transactions.js"; -import type { InternalWalletState } from "./wallet.js"; +import { getDenomInfo, type InternalWalletState } from "./wallet.js"; import { internalCreateWithdrawalGroup } from "./withdraw.js"; -const logger = new Logger("operations/recoup.ts"); +export const logger = new Logger("operations/recoup.ts"); /** * Store a recoup group record in the database after marking * a coin in the group as finished. */ -async function putGroupAsFinished( +export async function putGroupAsFinished( ws: InternalWalletState, tx: WalletDbReadWriteTransaction< ["recoupGroups", "denominations", "refreshGroups", "coins"] @@ -114,76 +113,6 @@ async function recoupRewardCoin( ); } -async function recoupWithdrawCoin( - ws: InternalWalletState, - recoupGroupId: string, - coinIdx: number, - coin: CoinRecord, - cs: WithdrawCoinSource, -): Promise<void> { - const reservePub = cs.reservePub; - const denomInfo = await ws.db.runReadOnlyTx(["denominations"], async (tx) => { - const denomInfo = await ws.getDenomInfo( - ws, - tx, - coin.exchangeBaseUrl, - coin.denomPubHash, - ); - return denomInfo; - }); - if (!denomInfo) { - // FIXME: We should at least emit some pending operation / warning for this? - return; - } - - const recoupRequest = await ws.cryptoApi.createRecoupRequest({ - blindingKey: coin.blindingKey, - coinPriv: coin.coinPriv, - coinPub: coin.coinPub, - denomPub: denomInfo.denomPub, - denomPubHash: coin.denomPubHash, - denomSig: coin.denomSig, - }); - const reqUrl = new URL(`/coins/${coin.coinPub}/recoup`, coin.exchangeBaseUrl); - logger.trace(`requesting recoup via ${reqUrl.href}`); - const resp = await ws.http.fetch(reqUrl.href, { - method: "POST", - body: recoupRequest, - }); - const recoupConfirmation = await readSuccessResponseJsonOrThrow( - resp, - codecForRecoupConfirmation(), - ); - - logger.trace(`got recoup confirmation ${j2s(recoupConfirmation)}`); - - if (recoupConfirmation.reserve_pub !== reservePub) { - throw Error(`Coin's reserve doesn't match reserve on recoup`); - } - - // FIXME: verify that our expectations about the amount match - - await ws.db.runReadWriteTx( - ["coins", "denominations", "recoupGroups", "refreshGroups"], - async (tx) => { - const recoupGroup = await tx.recoupGroups.get(recoupGroupId); - if (!recoupGroup) { - return; - } - if (recoupGroup.recoupFinishedPerCoin[coinIdx]) { - return; - } - const updatedCoin = await tx.coins.get(coin.coinPub); - if (!updatedCoin) { - return; - } - updatedCoin.status = CoinStatus.Dormant; - await tx.coins.put(updatedCoin); - await putGroupAsFinished(ws, tx, recoupGroup, coinIdx); - }, - ); -} - async function recoupRefreshCoin( ws: InternalWalletState, recoupGroupId: string, @@ -194,7 +123,7 @@ async function recoupRefreshCoin( const d = await ws.db.runReadOnlyTx( ["coins", "denominations"], async (tx) => { - const denomInfo = await ws.getDenomInfo( + const denomInfo = await getDenomInfo( ws, tx, coin.exchangeBaseUrl, @@ -258,13 +187,13 @@ async function recoupRefreshCoin( logger.warn("refresh old coin for recoup not found"); return; } - const oldCoinDenom = await ws.getDenomInfo( + const oldCoinDenom = await getDenomInfo( ws, tx, oldCoin.exchangeBaseUrl, oldCoin.denomPubHash, ); - const revokedCoinDenom = await ws.getDenomInfo( + const revokedCoinDenom = await getDenomInfo( ws, tx, revokedCoin.exchangeBaseUrl, diff --git a/packages/taler-wallet-core/src/refresh.ts b/packages/taler-wallet-core/src/refresh.ts index f1ee84f3e..cc5eff12c 100644 --- a/packages/taler-wallet-core/src/refresh.ts +++ b/packages/taler-wallet-core/src/refresh.ts @@ -99,7 +99,11 @@ import { constructTransactionIdentifier, notifyTransition, } from "./transactions.js"; -import { EXCHANGE_COINS_LOCK, InternalWalletState } from "./wallet.js"; +import { + EXCHANGE_COINS_LOCK, + getDenomInfo, + InternalWalletState, +} from "./wallet.js"; import { getCandidateWithdrawalDenomsTx } from "./withdraw.js"; const logger = new Logger("refresh.ts"); @@ -378,7 +382,7 @@ async function provideRefreshSession( const { availableAmount, availableDenoms } = await ws.db.runReadOnlyTx( ["denominations"], async (tx) => { - const oldDenom = await ws.getDenomInfo( + const oldDenom = await getDenomInfo( ws, tx, exch.exchangeBaseUrl, @@ -516,7 +520,7 @@ async function refreshMelt( const oldCoin = await tx.coins.get(refreshGroup.oldCoinPubs[coinIndex]); checkDbInvariant(!!oldCoin, "melt coin doesn't exist"); - const oldDenom = await ws.getDenomInfo( + const oldDenom = await getDenomInfo( ws, tx, oldCoin.exchangeBaseUrl, @@ -530,7 +534,7 @@ async function refreshMelt( const newCoinDenoms: RefreshNewDenomInfo[] = []; for (const dh of refreshSession.newDenoms) { - const newDenom = await ws.getDenomInfo( + const newDenom = await getDenomInfo( ws, tx, oldCoin.exchangeBaseUrl, @@ -819,7 +823,7 @@ async function refreshReveal( const oldCoin = await tx.coins.get(refreshGroup.oldCoinPubs[coinIndex]); checkDbInvariant(!!oldCoin, "melt coin doesn't exist"); - const oldDenom = await ws.getDenomInfo( + const oldDenom = await getDenomInfo( ws, tx, oldCoin.exchangeBaseUrl, @@ -833,7 +837,7 @@ async function refreshReveal( const newCoinDenoms: RefreshNewDenomInfo[] = []; for (const dh of refreshSession.newDenoms) { - const newDenom = await ws.getDenomInfo( + const newDenom = await getDenomInfo( ws, tx, oldCoin.exchangeBaseUrl, @@ -1162,7 +1166,7 @@ export async function calculateRefreshOutput( for (const ocp of oldCoinPubs) { const coin = await tx.coins.get(ocp.coinPub); checkDbInvariant(!!coin, "coin must be in database"); - const denom = await ws.getDenomInfo( + const denom = await getDenomInfo( ws, tx, coin.exchangeBaseUrl, @@ -1210,7 +1214,7 @@ async function applyRefresh( for (const ocp of oldCoinPubs) { const coin = await tx.coins.get(ocp.coinPub); checkDbInvariant(!!coin, "coin must be in database"); - const denom = await ws.getDenomInfo( + const denom = await getDenomInfo( ws, tx, coin.exchangeBaseUrl, @@ -1420,7 +1424,7 @@ export async function forceRefresh( if (!coin) { throw Error(`coin (pubkey ${c}) not found`); } - const denom = await ws.getDenomInfo( + const denom = await getDenomInfo( ws, tx, coin.exchangeBaseUrl, diff --git a/packages/taler-wallet-core/src/wallet.ts b/packages/taler-wallet-core/src/wallet.ts index f21db0531..79f7a1be5 100644 --- a/packages/taler-wallet-core/src/wallet.ts +++ b/packages/taler-wallet-core/src/wallet.ts @@ -310,6 +310,24 @@ async function fillDefaults(ws: InternalWalletState): Promise<void> { } } +export async function getDenomInfo( + ws: InternalWalletState, + tx: WalletDbReadOnlyTransaction<["denominations"]>, + exchangeBaseUrl: string, + denomPubHash: string, +): Promise<DenominationInfo | undefined> { + const key = `${exchangeBaseUrl}:${denomPubHash}`; + const cached = ws.denomCache[key]; + if (cached) { + return cached; + } + const d = await tx.denominations.get([exchangeBaseUrl, denomPubHash]); + if (d) { + return DenominationRecord.toDenomInfo(d); + } + return undefined; +} + /** * List bank accounts known to the wallet from * previous withdrawals. @@ -440,7 +458,7 @@ async function dumpCoins(ws: InternalWalletState): Promise<CoinDumpJson> { if (cs.type == CoinSourceType.Withdraw) { withdrawalReservePub = cs.reservePub; } - const denomInfo = await ws.getDenomInfo( + const denomInfo = await getDenomInfo( ws, tx, c.exchangeBaseUrl, @@ -1456,7 +1474,7 @@ export class InternalWalletState { initCalled = false; // FIXME: Use an LRU cache here. - private denomCache: Record<string, DenominationInfo> = {}; + denomCache: Record<string, DenominationInfo> = {}; /** * Promises that are waiting for a particular resource. @@ -1517,24 +1535,6 @@ export class InternalWalletState { } } - async getDenomInfo( - ws: InternalWalletState, - tx: WalletDbReadOnlyTransaction<["denominations"]>, - exchangeBaseUrl: string, - denomPubHash: string, - ): Promise<DenominationInfo | undefined> { - const key = `${exchangeBaseUrl}:${denomPubHash}`; - const cached = this.denomCache[key]; - if (cached) { - return cached; - } - const d = await tx.denominations.get([exchangeBaseUrl, denomPubHash]); - if (d) { - return DenominationRecord.toDenomInfo(d); - } - return undefined; - } - notify(n: WalletNotification): void { logger.trace(`Notification: ${j2s(n)}`); for (const l of this.listeners) { diff --git a/packages/taler-wallet-core/src/withdraw.ts b/packages/taler-wallet-core/src/withdraw.ts index a54295613..25c1e5129 100644 --- a/packages/taler-wallet-core/src/withdraw.ts +++ b/packages/taler-wallet-core/src/withdraw.ts @@ -146,7 +146,7 @@ import { WALLET_BANK_INTEGRATION_PROTOCOL_VERSION, WALLET_EXCHANGE_PROTOCOL_VERSION, } from "./versions.js"; -import type { InternalWalletState } from "./wallet.js"; +import { getDenomInfo, type InternalWalletState } from "./wallet.js"; /** * Logger for this file. @@ -678,12 +678,7 @@ async function processPlanchetGenerate( const denomPubHash = maybeDenomPubHash; const denom = await ws.db.runReadOnlyTx(["denominations"], async (tx) => { - return ws.getDenomInfo( - ws, - tx, - withdrawalGroup.exchangeBaseUrl, - denomPubHash, - ); + return getDenomInfo(ws, tx, withdrawalGroup.exchangeBaseUrl, denomPubHash); }); checkDbInvariant(!!denom); const r = await ws.cryptoApi.createPlanchet({ @@ -943,7 +938,7 @@ async function processPlanchetExchangeBatchRequest( logger.warn("processPlanchet: planchet already withdrawn"); continue; } - const denom = await ws.getDenomInfo( + const denom = await getDenomInfo( ws, tx, withdrawalGroup.exchangeBaseUrl, @@ -1057,7 +1052,7 @@ async function processPlanchetVerifyAndStoreCoin( logger.warn("processPlanchet: planchet already withdrawn"); return; } - const denomInfo = await ws.getDenomInfo( + const denomInfo = await getDenomInfo( ws, tx, withdrawalGroup.exchangeBaseUrl, @@ -1814,7 +1809,7 @@ export async function getExchangeWithdrawalInfo( await ws.db.runReadOnlyTx(["denominations"], async (tx) => { for (let i = 0; i < selectedDenoms.selectedDenoms.length; i++) { const ds = selectedDenoms.selectedDenoms[i]; - const denom = await ws.getDenomInfo( + const denom = await getDenomInfo( ws, tx, exchangeBaseUrl, |