diff options
author | Florian Dold <florian@dold.me> | 2024-05-10 18:23:37 +0200 |
---|---|---|
committer | Florian Dold <florian@dold.me> | 2024-05-10 18:24:00 +0200 |
commit | 2339438e4892dd3afc11538f45442a714ab5732f (patch) | |
tree | 250c7a76337450fff86766058e97af5d44a79997 | |
parent | 224bbb1d99a7f12a95322a4abb6a5e8f05fca68b (diff) | |
download | wallet-core-master.tar.xz |
-rw-r--r-- | packages/taler-util/src/taler-crypto.ts | 17 | ||||
-rw-r--r-- | packages/taler-util/src/wallet-types.ts | 12 | ||||
-rw-r--r-- | packages/taler-wallet-core/src/crypto/cryptoImplementation.ts | 35 | ||||
-rw-r--r-- | packages/taler-wallet-core/src/deposits.ts | 2 | ||||
-rw-r--r-- | packages/taler-wallet-core/src/wallet-api-types.ts | 8 | ||||
-rw-r--r-- | packages/taler-wallet-core/src/wallet.ts | 35 |
6 files changed, 99 insertions, 10 deletions
diff --git a/packages/taler-util/src/taler-crypto.ts b/packages/taler-util/src/taler-crypto.ts index e587773e2..950161b10 100644 --- a/packages/taler-util/src/taler-crypto.ts +++ b/packages/taler-util/src/taler-crypto.ts @@ -21,23 +21,23 @@ /** * Imports. */ -import * as nacl from "./nacl-fast.js"; -import { hmacSha256, hmacSha512 } from "./kdf.js"; import bigint from "big-integer"; +import * as fflate from "fflate"; +import { AmountLike, Amounts } from "./amounts.js"; import * as argon2 from "./argon2.js"; +import { canonicalJson } from "./helpers.js"; +import { hmacSha256, hmacSha512 } from "./kdf.js"; +import { Logger } from "./logging.js"; +import * as nacl from "./nacl-fast.js"; +import { secretbox } from "./nacl-fast.js"; import { CoinEnvelope, CoinPublicKeyString, - DenominationPubKey, DenomKeyType, + DenominationPubKey, HashCodeString, } from "./taler-types.js"; -import { Logger } from "./logging.js"; -import { secretbox } from "./nacl-fast.js"; -import * as fflate from "fflate"; -import { canonicalJson } from "./helpers.js"; import { TalerProtocolDuration, TalerProtocolTimestamp } from "./time.js"; -import { AmountLike, Amounts } from "./amounts.js"; export type Flavor<T, FlavorT extends string> = T & { _flavor?: `taler.${FlavorT}`; @@ -974,6 +974,7 @@ export function hashWire(paytoUri: string, salt: string): string { export enum TalerSignaturePurpose { MERCHANT_TRACK_TRANSACTION = 1103, WALLET_RESERVE_WITHDRAW = 1200, + WALLET_RESERVE_HISTORY = 1208, WALLET_COIN_DEPOSIT = 1201, GLOBAL_FEES = 1022, MASTER_DENOMINATION_KEY_VALIDITY = 1025, diff --git a/packages/taler-util/src/wallet-types.ts b/packages/taler-util/src/wallet-types.ts index ec6cb6f58..b9fd24754 100644 --- a/packages/taler-util/src/wallet-types.ts +++ b/packages/taler-util/src/wallet-types.ts @@ -3010,6 +3010,18 @@ export interface TestingWaitTransactionRequest { txState: TransactionState; } +export interface TestingGetReserveHistoryRequest { + reservePub: string; + exchangeBaseUrl: string; +} + +export const codecForTestingGetReserveHistoryRequest = + (): Codec<TestingGetReserveHistoryRequest> => + buildCodecForObject<TestingGetReserveHistoryRequest>() + .property("reservePub", codecForString()) + .property("exchangeBaseUrl", codecForString()) + .build("TestingGetReserveHistoryRequest"); + export interface TestingGetDenomStatsRequest { exchangeBaseUrl: string; } diff --git a/packages/taler-wallet-core/src/crypto/cryptoImplementation.ts b/packages/taler-wallet-core/src/crypto/cryptoImplementation.ts index 0745d70c4..2a2958a71 100644 --- a/packages/taler-wallet-core/src/crypto/cryptoImplementation.ts +++ b/packages/taler-wallet-core/src/crypto/cryptoImplementation.ts @@ -214,6 +214,10 @@ export interface TalerCryptoInterface { signPurseCreation(req: SignPurseCreationRequest): Promise<EddsaSigningResult>; + signReserveHistoryReq( + req: SignReserveHistoryReqRequest, + ): Promise<SignReserveHistoryReqResponse>; + signPurseDeposits( req: SignPurseDepositsRequest, ): Promise<SignPurseDepositsResponse>; @@ -438,6 +442,11 @@ export const nullCrypto: TalerCryptoInterface = { ): Promise<SignCoinHistoryResponse> { throw new Error("Function not implemented."); }, + signReserveHistoryReq: function ( + req: SignReserveHistoryReqRequest, + ): Promise<SignReserveHistoryReqResponse> { + throw new Error("Function not implemented."); + }, }; export type WithArg<X> = X extends (req: infer T) => infer R @@ -475,6 +484,15 @@ export interface SignPurseCreationRequest { minAge: number; } +export interface SignReserveHistoryReqRequest { + reservePriv: string; + startOffset: number; +} + +export interface SignReserveHistoryReqResponse { + sig: string; +} + export interface SpendCoinDetails { coinPub: string; coinPriv: string; @@ -1730,6 +1748,23 @@ export const nativeCryptoR: TalerCryptoInterfaceR = { sig: sigResp.sig, }; }, + async signReserveHistoryReq( + tci: TalerCryptoInterfaceR, + req: SignReserveHistoryReqRequest, + ): Promise<SignReserveHistoryReqResponse> { + const reserveHistoryBlob = buildSigPS( + TalerSignaturePurpose.WALLET_RESERVE_HISTORY, + ) + .put(bufferForUint64(req.startOffset)) + .build(); + const sigResp = await tci.eddsaSign(tci, { + msg: encodeCrock(reserveHistoryBlob), + priv: req.reservePriv, + }); + return { + sig: sigResp.sig, + }; + }, }; export interface EddsaSignRequest { diff --git a/packages/taler-wallet-core/src/deposits.ts b/packages/taler-wallet-core/src/deposits.ts index dbba55247..c4cd98d73 100644 --- a/packages/taler-wallet-core/src/deposits.ts +++ b/packages/taler-wallet-core/src/deposits.ts @@ -776,7 +776,7 @@ async function processDepositGroupPendingTrack( { storeNames: ["coins"] }, async (tx) => { const coinRecord = await tx.coins.get(coinPub); - checkDbInvariant(!!coinRecord); + checkDbInvariant(!!coinRecord, `coin ${coinPub} not found in DB`); return coinRecord.exchangeBaseUrl; }, ); diff --git a/packages/taler-wallet-core/src/wallet-api-types.ts b/packages/taler-wallet-core/src/wallet-api-types.ts index ed882708c..9a8ea8470 100644 --- a/packages/taler-wallet-core/src/wallet-api-types.ts +++ b/packages/taler-wallet-core/src/wallet-api-types.ts @@ -270,6 +270,7 @@ export enum WalletApiOperation { TestingListTaskForTransaction = "testingListTasksForTransaction", TestingGetDenomStats = "testingGetDenomStats", TestingPing = "testingPing", + TestingGetReserveHistory = "testingGetReserveHistory", } // group: Initialization @@ -1187,6 +1188,12 @@ export type TestingPingOp = { response: EmptyObject; }; +export type TestingGetReserveHistoryOp = { + op: WalletApiOperation.TestingGetReserveHistory; + request: EmptyObject; + response: any; +}; + /** * Get stats about an exchange denomination. */ @@ -1329,6 +1336,7 @@ export type WalletOperations = { [WalletApiOperation.PrepareBankIntegratedWithdrawal]: PrepareBankIntegratedWithdrawalOp; [WalletApiOperation.ConfirmWithdrawal]: ConfirmWithdrawalOp; [WalletApiOperation.CanonicalizeBaseUrl]: CanonicalizeBaseUrlOp; + [WalletApiOperation.TestingGetReserveHistory]: TestingGetReserveHistoryOp; }; export type WalletCoreRequestType< diff --git a/packages/taler-wallet-core/src/wallet.ts b/packages/taler-wallet-core/src/wallet.ts index ea47ffad7..fe03dbf62 100644 --- a/packages/taler-wallet-core/src/wallet.ts +++ b/packages/taler-wallet-core/src/wallet.ts @@ -134,6 +134,7 @@ import { codecForSuspendTransaction, codecForTestPayArgs, codecForTestingGetDenomStatsRequest, + codecForTestingGetReserveHistoryRequest, codecForTestingListTasksForTransactionRequest, codecForTestingSetTimetravelRequest, codecForTransactionByIdRequest, @@ -154,7 +155,10 @@ import { setDangerousTimetravel, validateIban, } from "@gnu-taler/taler-util"; -import type { HttpRequestLibrary } from "@gnu-taler/taler-util/http"; +import { + readSuccessResponseJsonOrThrow, + type HttpRequestLibrary, +} from "@gnu-taler/taler-util/http"; import { getUserAttentions, getUserAttentionsUnreadCount, @@ -909,6 +913,35 @@ async function dispatchRequestInternal( restrictAge: req.restrictAge, }); } + case WalletApiOperation.TestingGetReserveHistory: { + const req = codecForTestingGetReserveHistoryRequest().decode(payload); + const reserve = await wex.db.runReadOnlyTx( + { storeNames: ["reserves"] }, + async (tx) => { + return tx.reserves.indexes.byReservePub.get(req.reservePub); + }, + ); + if (!reserve) { + throw Error("no reserve pub found"); + } + const sigResp = await wex.cryptoApi.signReserveHistoryReq({ + reservePriv: reserve.reservePriv, + startOffset: 0, + }); + const exchangeBaseUrl = req.exchangeBaseUrl; + const url = new URL( + `reserves/${req.reservePub}/history`, + exchangeBaseUrl, + ); + const resp = await wex.http.fetch(url.href, { + headers: { ["Taler-Reserve-History-Signature"]: sigResp.sig }, + }); + const historyJson = await readSuccessResponseJsonOrThrow( + resp, + codecForAny(), + ); + return historyJson; + } case WalletApiOperation.AcceptManualWithdrawal: { const req = codecForAcceptManualWithdrawalRequest().decode(payload); const res = await createManualWithdrawal(wex, { |