diff options
Diffstat (limited to 'packages/taler-wallet-core/src/operations/exchanges.ts')
-rw-r--r-- | packages/taler-wallet-core/src/operations/exchanges.ts | 90 |
1 files changed, 63 insertions, 27 deletions
diff --git a/packages/taler-wallet-core/src/operations/exchanges.ts b/packages/taler-wallet-core/src/operations/exchanges.ts index 6569cb394..e89364ad1 100644 --- a/packages/taler-wallet-core/src/operations/exchanges.ts +++ b/packages/taler-wallet-core/src/operations/exchanges.ts @@ -64,6 +64,7 @@ import { readSuccessResponseJsonOrThrow, readSuccessResponseTextOrThrow, } from "../util/http.js"; +import { checkDbInvariant } from "../util/invariants.js"; import { DbAccess, GetReadOnlyAccess, @@ -168,7 +169,11 @@ export async function getExchangeDetails( return; } const { currency, masterPublicKey } = dp; - return await tx.exchangeDetails.get([r.baseUrl, currency, masterPublicKey]); + return await tx.exchangeDetails.indexes.byPointer.get([ + r.baseUrl, + currency, + masterPublicKey, + ]); } getExchangeDetails.makeContext = (db: DbAccess<typeof WalletStoresV1>) => @@ -205,7 +210,7 @@ export async function updateExchangeTermsOfService( /** * Mark a ToS version as accepted by the user. - * + * * @param etag version of the ToS to accept, or current ToS version of not given */ export async function acceptExchangeTermsOfService( @@ -568,10 +573,14 @@ export async function updateExchangeFromUrlHandler( const now = AbsoluteTime.now(); baseUrl = canonicalizeBaseUrl(baseUrl); - + let isNewExchange = true; const { exchange, exchangeDetails } = await ws.db .mktx((x) => [x.exchanges, x.exchangeDetails]) .runReadWrite(async (tx) => { + let oldExch = await tx.exchanges.get(baseUrl); + if (oldExch) { + isNewExchange = false; + } return provideExchangeRecordInTx(ws, tx, baseUrl, now); }); @@ -637,10 +646,13 @@ export async function updateExchangeFromUrlHandler( logger.trace("updating exchange info in database"); + let detailsPointerChanged = false; + const updated = await ws.db .mktx((x) => [ x.exchanges, x.exchangeDetails, + x.exchangeSignkeys, x.denominations, x.coins, x.refreshGroups, @@ -652,42 +664,63 @@ export async function updateExchangeFromUrlHandler( logger.warn(`exchange ${baseUrl} no longer present`); return; } - let details = await getExchangeDetails(tx, r.baseUrl); - if (details) { + let existingDetails = await getExchangeDetails(tx, r.baseUrl); + let acceptedTosEtag = undefined; + if (!existingDetails) { + detailsPointerChanged = true; + } + if (existingDetails) { + acceptedTosEtag = existingDetails.tosAccepted?.etag; + if (existingDetails.masterPublicKey !== keysInfo.masterPublicKey) { + detailsPointerChanged = true; + } + if (existingDetails.currency !== keysInfo.currency) { + detailsPointerChanged = true; + } // FIXME: We need to do some consistency checks! } - // FIXME: validate signing keys and merge with old set - details = { + let existingTosAccepted = existingDetails?.tosAccepted; + const newDetails = { + rowId: existingDetails?.rowId, auditors: keysInfo.auditors, currency: keysInfo.currency, masterPublicKey: keysInfo.masterPublicKey, protocolVersionRange: keysInfo.protocolVersion, - signingKeys: keysInfo.signingKeys, reserveClosingDelay: keysInfo.reserveClosingDelay, globalFees, exchangeBaseUrl: r.baseUrl, wireInfo, - tosCurrentEtag: tosDownload.tosContentType, - tosAccepted: tosHasBeenAccepted - ? { - etag: tosDownload.tosEtag, - timestamp: TalerProtocolTimestamp.now(), - } - : undefined, + tosCurrentEtag: tosDownload.tosEtag, + tosAccepted: existingTosAccepted, }; - // FIXME: only update if pointer got updated r.lastUpdate = TalerProtocolTimestamp.now(); r.nextUpdate = keysInfo.expiry; // New denominations might be available. r.nextRefreshCheck = TalerProtocolTimestamp.now(); - r.detailsPointer = { - currency: details.currency, - masterPublicKey: details.masterPublicKey, - // FIXME: only change if pointer really changed - updateClock: TalerProtocolTimestamp.now(), - }; + if (detailsPointerChanged) { + r.detailsPointer = { + currency: newDetails.currency, + masterPublicKey: newDetails.masterPublicKey, + updateClock: TalerProtocolTimestamp.now(), + }; + } await tx.exchanges.put(r); - await tx.exchangeDetails.put(details); + logger.info(`existing details ${j2s(existingDetails)}`); + logger.info(`inserting new details ${j2s(newDetails)}`); + const drRowId = await tx.exchangeDetails.put(newDetails); + checkDbInvariant(typeof drRowId.key === "number"); + + for (const sk of keysInfo.signingKeys) { + // FIXME: validate signing keys before inserting them + await tx.exchangeSignKeys.put({ + exchangeDetailsRowId: drRowId.key, + masterSig: sk.master_sig, + signkeyPub: sk.key, + stampEnd: sk.stamp_end, + stampExpire: sk.stamp_expire, + stampStart: sk.stamp_start, + }); + } logger.info("updating denominations in database"); const currentDenomSet = new Set<string>( @@ -773,7 +806,7 @@ export async function updateExchangeFromUrlHandler( } return { exchange: r, - exchangeDetails: details, + exchangeDetails: newDetails, }; }); @@ -791,9 +824,12 @@ export async function updateExchangeFromUrlHandler( logger.trace("done updating exchange info in database"); - ws.notify({ - type: NotificationType.ExchangeAdded, - }); + if (isNewExchange) { + ws.notify({ + type: NotificationType.ExchangeAdded, + }); + } + return { type: OperationAttemptResultType.Finished, result: { |