commit 62f078545a272d0abff0b52d865e1159ed11d17e
parent e76071abac37fae340b8c126438a0b4f6553c857
Author: Florian Dold <florian@dold.me>
Date: Fri, 13 Feb 2026 19:53:36 +0100
-refactor
Diffstat:
1 file changed, 18 insertions(+), 105 deletions(-)
diff --git a/packages/taler-wallet-core/src/refresh.ts b/packages/taler-wallet-core/src/refresh.ts
@@ -23,7 +23,6 @@
* Imports.
*/
import {
- AgeCommitment,
AgeRestriction,
AmountJson,
AmountLike,
@@ -35,7 +34,6 @@ import {
codecForCoinHistoryResponse,
codecForExchangeMeltResponse,
codecForExchangeRevealMeltResponseV2,
- CoinPublicKeyString,
CoinRefreshRequest,
CoinStatus,
DenominationInfo,
@@ -43,7 +41,6 @@ import {
Duration,
encodeCrock,
ExchangeMeltRequestV2,
- ExchangeRefreshRevealRequest,
ExchangeRefreshRevealRequestV2,
ExchangeRefundRequest,
fnutil,
@@ -90,11 +87,7 @@ import {
TaskRunResultType,
TransactionContext,
} from "./common.js";
-import { TalerCryptoInterface } from "./crypto/cryptoImplementation.js";
-import {
- DerivedRefreshSession,
- RefreshNewDenomInfo,
-} from "./crypto/cryptoTypes.js";
+import { RefreshNewDenomInfo } from "./crypto/cryptoTypes.js";
import { CryptoApiStoppedError } from "./crypto/workers/crypto-dispatcher.js";
import {
CoinAvailabilityRecord,
@@ -116,8 +109,6 @@ import {
import { selectWithdrawalDenominations } from "./denomSelection.js";
import { fetchFreshExchange, getScopeForAllExchanges } from "./exchanges.js";
import {
- applyNotifyTransition,
- BalanceEffect,
constructTransactionIdentifier,
isUnsuccessfulTransaction,
} from "./transactions.js";
@@ -863,7 +854,7 @@ async function handleRefreshMeltGone(
],
},
async (tx) => {
- const rg = await tx.refreshGroups.get(ctx.refreshGroupId);
+ const [rg, h] = await ctx.getRecordHandle(tx);
if (!rg) {
return;
}
@@ -882,10 +873,9 @@ async function handleRefreshMeltGone(
throw Error("db invariant failed: missing refresh session in database");
}
refreshSession.lastError = errDetails;
- await destroyRefreshSession(ctx.wex, tx, rg, refreshSession);
- await tx.refreshGroups.put(rg);
- await ctx.updateTransactionMeta(tx);
await tx.refreshSessions.put(refreshSession);
+ await destroyRefreshSession(ctx.wex, tx, rg, refreshSession);
+ await h.update(rg);
},
);
}
@@ -983,7 +973,7 @@ async function handleRefreshMeltConflict(
],
},
async (tx) => {
- const rg = await tx.refreshGroups.get(ctx.refreshGroupId);
+ const [rg, h] = await ctx.getRecordHandle(tx);
if (!rg) {
return;
}
@@ -1005,9 +995,8 @@ async function handleRefreshMeltConflict(
);
}
refreshSession.lastError = errDetails;
- await tx.refreshGroups.put(rg);
- await ctx.updateTransactionMeta(tx);
await tx.refreshSessions.put(refreshSession);
+ await h.update(rg);
} else {
// Try again with new denoms!
rg.inputPerCoin[coinIndex] = historyJson.balance;
@@ -1055,7 +1044,7 @@ async function handleRefreshMeltNotFound(
],
},
async (tx) => {
- const rg = await tx.refreshGroups.get(ctx.refreshGroupId);
+ const [rg, h] = await ctx.getRecordHandle(tx);
if (!rg) {
return;
}
@@ -1073,73 +1062,14 @@ async function handleRefreshMeltNotFound(
if (!refreshSession) {
throw Error("db invariant failed: missing refresh session in database");
}
- await destroyRefreshSession(ctx.wex, tx, rg, refreshSession);
refreshSession.lastError = errDetails;
- await tx.refreshGroups.put(rg);
- await ctx.updateTransactionMeta(tx);
await tx.refreshSessions.put(refreshSession);
+ await destroyRefreshSession(ctx.wex, tx, rg, refreshSession);
+ await h.update(rg);
},
);
}
-export async function assembleRefreshRevealRequest(args: {
- cryptoApi: TalerCryptoInterface;
- derived: DerivedRefreshSession;
- norevealIndex: number;
- oldCoinPub: CoinPublicKeyString;
- oldCoinPriv: string;
- newDenoms: {
- denomPubHash: string;
- count: number;
- }[];
- oldAgeCommitment?: AgeCommitment;
-}): Promise<ExchangeRefreshRevealRequest> {
- const {
- derived,
- norevealIndex,
- cryptoApi,
- oldCoinPriv,
- oldCoinPub,
- newDenoms,
- } = args;
- const privs = Array.from(derived.transferPrivs);
- privs.splice(norevealIndex, 1);
-
- const planchets = derived.planchets[norevealIndex];
- if (!planchets) {
- throw Error("refresh index error");
- }
-
- const newDenomsFlat: string[] = [];
- const linkSigs: string[] = [];
-
- for (let i = 0; i < newDenoms.length; i++) {
- const dsel = newDenoms[i];
- for (let j = 0; j < dsel.count; j++) {
- const newCoinIndex = linkSigs.length;
- const linkSig = await cryptoApi.signCoinLink({
- coinEv: planchets[newCoinIndex].coinEv,
- newDenomHash: dsel.denomPubHash,
- oldCoinPriv: oldCoinPriv,
- oldCoinPub: oldCoinPub,
- transferPub: derived.transferPubs[norevealIndex],
- });
- linkSigs.push(linkSig.sig);
- newDenomsFlat.push(dsel.denomPubHash);
- }
- }
-
- const req: ExchangeRefreshRevealRequest = {
- coin_evs: planchets.map((x) => x.coinEv),
- new_denoms_h: newDenomsFlat,
- transfer_privs: privs,
- transfer_pub: derived.transferPubs[norevealIndex],
- link_sigs: linkSigs,
- old_age_commitment: args.oldAgeCommitment?.publicKeys,
- };
- return req;
-}
-
async function refreshReveal(
wex: WalletExecutionContext,
refreshGroupId: string,
@@ -1339,7 +1269,7 @@ async function refreshReveal(
],
},
async (tx) => {
- const rg = await tx.refreshGroups.get(refreshGroupId);
+ const [rg, h] = await ctx.getRecordHandle(tx);
if (!rg) {
logger.warn("no refresh session found");
return;
@@ -1383,8 +1313,7 @@ async function refreshReveal(
car.freshCoinCount++;
await tx.coinAvailability.put(car);
}
- await tx.refreshGroups.put(rg);
- await ctx.updateTransactionMeta(tx);
+ await h.update(rg);
},
);
logger.trace("refresh finished (end of reveal)");
@@ -1407,7 +1336,7 @@ async function handleRefreshRevealError(
],
},
async (tx) => {
- const rg = await tx.refreshGroups.get(ctx.refreshGroupId);
+ const [rg, h] = await ctx.getRecordHandle(tx);
if (!rg) {
return;
}
@@ -1427,9 +1356,8 @@ async function handleRefreshRevealError(
}
refreshSession.lastError = errDetails;
await destroyRefreshSession(ctx.wex, tx, rg, refreshSession);
- await tx.refreshGroups.put(rg);
await tx.refreshSessions.put(refreshSession);
- await ctx.updateTransactionMeta(tx);
+ await h.update(rg);
},
);
}
@@ -1521,7 +1449,7 @@ export async function processRefreshGroup(
],
},
async (tx) => {
- const rg = await tx.refreshGroups.get(refreshGroupId);
+ const [rg, h] = await ctx.getRecordHandle(tx);
if (!rg) {
return false;
}
@@ -1531,8 +1459,6 @@ export async function processRefreshGroup(
default:
return false;
}
- const oldTxState = computeRefreshTransactionState(rg);
- const oldStId = rg.operationStatus;
const allFinal = fnutil.all(
rg.statusPerCoin,
(x) =>
@@ -1555,19 +1481,7 @@ export async function processRefreshGroup(
rg.operationStatus = RefreshOperationStatus.Finished;
}
await makeCoinsVisible(wex, tx, ctx.transactionId);
- await tx.refreshGroups.put(rg);
- await ctx.updateTransactionMeta(tx);
- const newTxState = computeRefreshTransactionState(rg);
- applyNotifyTransition(tx.notify, ctx.transactionId, {
- oldTxState,
- newTxState,
- balanceEffect:
- rg.operationStatus === RefreshOperationStatus.Failed
- ? BalanceEffect.Any
- : BalanceEffect.PreserveUserVisible,
- oldStId,
- newStId: rg.operationStatus,
- });
+ await h.update(rg);
return true;
}
return false;
@@ -1897,14 +1811,14 @@ export async function createRefreshGroup(
};
}
-export async function redenominateRefresh(
+async function redenominateRefresh(
wex: WalletExecutionContext,
refreshGroupId: string,
): Promise<TaskRunResult> {
const ctx = new RefreshTransactionContext(wex, refreshGroupId);
logger.info(`re-denominating refresh group ${refreshGroupId}`);
return await wex.db.runAllStoresReadWriteTx({}, async (tx) => {
- const refreshGroup = await tx.refreshGroups.get(refreshGroupId);
+ const [refreshGroup, h] = await ctx.getRecordHandle(tx);
if (!refreshGroup) {
return TaskRunResult.finished();
}
@@ -1948,8 +1862,7 @@ export async function redenominateRefresh(
);
refreshGroup.operationStatus = RefreshOperationStatus.Pending;
- await tx.refreshGroups.put(refreshGroup);
- await ctx.updateTransactionMeta(tx);
+ await h.update(refreshGroup);
return TaskRunResult.progress();
});
}