taler-typescript-core

Wallet core logic and WebUIs for various components
Log | Files | Refs | Submodules | README | LICENSE

commit cccec1b0c826bff69d9e809f4bd8f33926e2f150
parent c6d64e20bd90d81504c4e64b01b8c07cf944da9f
Author: Florian Dold <florian@dold.me>
Date:   Fri, 13 Feb 2026 13:25:20 +0100

wallet-core: use index for denom families instead of manual hashing

Diffstat:
Mpackages/taler-wallet-core/src/db.ts | 47++++++++++++++++++++++++++++++-----------------
Mpackages/taler-wallet-core/src/exchanges.ts | 26+++++++++++++-------------
2 files changed, 43 insertions(+), 30 deletions(-)

diff --git a/packages/taler-wallet-core/src/db.ts b/packages/taler-wallet-core/src/db.ts @@ -81,7 +81,6 @@ import { codecForAny, encodeCrock, hash, - hashTruncate32, j2s, stringToBytes, stringifyScopeInfo, @@ -175,7 +174,7 @@ export const CURRENT_DB_CONFIG_KEY = "currentMainDbName"; * backwards-compatible way or object stores and indices * are added. */ -export const WALLET_DB_MINOR_VERSION = 27; +export const WALLET_DB_MINOR_VERSION = 28; declare const symDbProtocolTimestamp: unique symbol; @@ -272,10 +271,6 @@ export interface DenomFamilyParams { feeRefund: AmountString; } -export function hashDenomFamilyParams(dfp: DenomFamilyParams): string { - return encodeCrock(hashTruncate32(stringToBytes(canonicalJson(dfp) + "\0"))); -} - /** * Format of the operation status code: 0x0abc_nnnn @@ -510,11 +505,10 @@ export interface DenomFees { export interface DenominationFamilyRecord { denominationFamilySerial?: number; - /** - * Hash (32 byte truncated SHA-512) of canonicalized parameter JSON. - */ - familyParamsHash: string; familyParams: DenomFamilyParams; + + // Reserved legacy fields: + // * familyParamsHash } /** @@ -3230,13 +3224,23 @@ export const WalletStoresV1 = { versionAdded: 27, }, ), - byFamilyParamsHash: describeIndex( - "byFamilyParamsHash", - "familyParamsHash", + byFamilyParms: describeIndex( + "byFamilyParams", + [ + "familyParams.exchangeBaseUrl", + "familyParams.exchangeMasterPub", + "familyParams.value", + "familyParams.feeWithdraw", + "familyParams.feeDeposit", + "familyParams.feeRefresh", + "familyParams.feeRefund", + ], { - versionAdded: 27, + versionAdded: 28, }, ), + // Reserved legacy index names: + // * byFamilyParamsHash }, ), exchanges: describeStore( @@ -3964,16 +3968,25 @@ async function fixup20260203DenomFamilyMigration( continue; } } - const fph = hashDenomFamilyParams(fp); + const familyParamsIndexKey = [ + fp.exchangeBaseUrl, + fp.exchangeMasterPub, + fp.value, + fp.feeWithdraw, + fp.feeDeposit, + fp.feeRefresh, + fp.feeRefund, + ]; const dfRec = - await tx.denominationFamilies.indexes.byFamilyParamsHash.get(fph); + await tx.denominationFamilies.indexes.byFamilyParms.get( + familyParamsIndexKey, + ); let denominationFamilySerial; if (dfRec) { denominationFamilySerial = dfRec.denominationFamilySerial; } else { const insRes = await tx.denominationFamilies.put({ familyParams: fp, - familyParamsHash: fph, }); denominationFamilySerial = insRes.key; } diff --git a/packages/taler-wallet-core/src/exchanges.ts b/packages/taler-wallet-core/src/exchanges.ts @@ -154,7 +154,6 @@ import { WalletDbHelpers, WalletDbReadOnlyTransaction, WalletDbReadWriteTransaction, - hashDenomFamilyParams, timestampAbsoluteFromDb, timestampOptionalPreciseFromDb, timestampPreciseFromDb, @@ -1814,9 +1813,7 @@ export async function updateExchangeFromUrlHandler( let peerPaymentsDisabled = checkPeerPaymentsDisabled(keysInfo); const denomInfos: DenominationInfo[] = []; - // Se of all current denoms offered by exchange const currentDenomSet = new Set<string>(); - const fpMap = new Map<DenominationInfo, string>(); for (const denomFamily of keysInfo.denominations) { switch (denomFamily.cipher) { case "CS": @@ -1864,7 +1861,6 @@ export async function updateExchangeFromUrlHandler( masterSig: denom.master_sig, }; denomInfos.push(di); - fpMap.set(di, hashDenomFamilyParams(fp)); currentDenomSet.add(denomPubHash); } } @@ -2046,14 +2042,18 @@ export async function updateExchangeFromUrlHandler( for (const currentDenom of denomInfos) { // FIXME: Check if we really already need the denomination. - const familyParamHash = fpMap.get(currentDenom); - if (!familyParamHash) { - logger.error("missing family param hash"); - continue; - } + const familyParamsIndexKey = [ + currentDenom.exchangeBaseUrl, + currentDenom.exchangeMasterPub, + currentDenom.value, + currentDenom.feeWithdraw, + currentDenom.feeDeposit, + currentDenom.feeRefresh, + currentDenom.feeRefund, + ]; let fpRec: DenominationFamilyRecord | undefined = - await tx.denominationFamilies.indexes.byFamilyParamsHash.get( - familyParamHash, + await tx.denominationFamilies.indexes.byFamilyParms.get( + familyParamsIndexKey, ); let denominationFamilySerial; if (fpRec == null) { @@ -2068,7 +2068,6 @@ export async function updateExchangeFromUrlHandler( }; fpRec = { familyParams: fp, - familyParamsHash: familyParamHash, }; const insRes = await tx.denominationFamilies.put(fpRec); denominationFamilySerial = insRes.key; @@ -2144,6 +2143,7 @@ export async function updateExchangeFromUrlHandler( logger.info( `setting denomination ${x.denomPubHash} to offered=false`, ); + await tx.denominations.put(x); } } else { if (!x.isOffered) { @@ -2151,9 +2151,9 @@ export async function updateExchangeFromUrlHandler( logger.info( `setting denomination ${x.denomPubHash} to offered=true`, ); + await tx.denominations.put(x); } } - await tx.denominations.put(x); } logger.trace("done updating denominations in database");