diff --git a/packages/taler-util/src/backupTypes.ts b/packages/taler-util/src/backupTypes.ts index 8663850c9..41a9ce98e 100644 --- a/packages/taler-util/src/backupTypes.ts +++ b/packages/taler-util/src/backupTypes.ts @@ -1023,6 +1023,8 @@ export interface BackupExchangeWireFee { */ wire_fee: string; + wad_fee: string; + /** * Fees to close and refund a reserve. */ diff --git a/packages/taler-util/src/talerCrypto.ts b/packages/taler-util/src/talerCrypto.ts index 83e5dc6fe..358da9dac 100644 --- a/packages/taler-util/src/talerCrypto.ts +++ b/packages/taler-util/src/talerCrypto.ts @@ -25,6 +25,7 @@ import * as nacl from "./nacl-fast.js"; import { kdf, kdfKw } from "./kdf.js"; import bigint from "big-integer"; import { + Base32String, CoinEnvelope, DenominationPubKey, DenomKeyType, @@ -598,6 +599,15 @@ export function hash(d: Uint8Array): Uint8Array { return nacl.hash(d); } +/** + * Hash the input with SHA-512 and truncate the result + * to 32 bytes. + */ +export function hashTruncate32(d: Uint8Array): Uint8Array { + const sha512HashCode = nacl.hash(d); + return sha512HashCode.subarray(0, 32); +} + export function hashCoinEv( coinEv: CoinEnvelope, denomPubHash: HashCodeString, @@ -608,7 +618,6 @@ export function hashCoinEv( return hashContext.finish(); } - const logger = new Logger("talerCrypto.ts"); export function hashCoinEvInner( @@ -683,7 +692,6 @@ export interface FreshCoin { bks: Uint8Array; } - function bufferForUint32(n: number): Uint8Array { const arrBuf = new ArrayBuffer(4); const buf = new Uint8Array(arrBuf); diff --git a/packages/taler-util/src/talerTypes.ts b/packages/taler-util/src/talerTypes.ts index 59d37dece..4581f0b6a 100644 --- a/packages/taler-util/src/talerTypes.ts +++ b/packages/taler-util/src/talerTypes.ts @@ -738,6 +738,8 @@ export class WireFeesJson { */ wire_fee: string; + wad_fee: string; + /** * Cost of clising a reserve. */ @@ -1356,6 +1358,7 @@ export const codecForWireFeesJson = (): Codec => buildCodecForObject() .property("wire_fee", codecForString()) .property("closing_fee", codecForString()) + .property("wad_fee", codecForString()) .property("sig", codecForString()) .property("start_date", codecForTimestamp) .property("end_date", codecForTimestamp) diff --git a/packages/taler-wallet-cli/src/harness/harness.ts b/packages/taler-wallet-cli/src/harness/harness.ts index b4d2884d1..b24e828bf 100644 --- a/packages/taler-wallet-cli/src/harness/harness.ts +++ b/packages/taler-wallet-cli/src/harness/harness.ts @@ -1443,6 +1443,7 @@ export class ExchangeService implements ExchangeServiceInterface { accTargetType, `${this.exchangeConfig.currency}:0.01`, `${this.exchangeConfig.currency}:0.01`, + `${this.exchangeConfig.currency}:0.01`, "upload", ], ); diff --git a/packages/taler-wallet-core/src/crypto/workers/cryptoImplementation.ts b/packages/taler-wallet-core/src/crypto/workers/cryptoImplementation.ts index bd18e8d2e..f9cc63ecc 100644 --- a/packages/taler-wallet-core/src/crypto/workers/cryptoImplementation.ts +++ b/packages/taler-wallet-core/src/crypto/workers/cryptoImplementation.ts @@ -48,6 +48,7 @@ import { hashCoinEv, hashCoinEvInner, hashDenomPub, + hashTruncate32, keyExchangeEcdheEddsa, Logger, MakeSyncSignatureRequest, @@ -329,6 +330,7 @@ export class CryptoImplementation { .put(timestampRoundedToBuffer(wf.endStamp)) .put(amountToBuffer(wf.wireFee)) .put(amountToBuffer(wf.closingFee)) + .put(amountToBuffer(wf.wadFee)) .build(); const sig = decodeCrock(wf.sig); const pub = decodeCrock(masterPub); @@ -376,7 +378,7 @@ export class CryptoImplementation { sig: string, masterPub: string, ): boolean { - const paytoHash = hash(stringToBytes(paytoUri + "\0")); + const paytoHash = hashTruncate32(stringToBytes(paytoUri + "\0")); const p = buildSigPS(TalerSignaturePurpose.MASTER_WIRE_DETAILS) .put(paytoHash) .build(); diff --git a/packages/taler-wallet-core/src/db.ts b/packages/taler-wallet-core/src/db.ts index 410311530..23239069e 100644 --- a/packages/taler-wallet-core/src/db.ts +++ b/packages/taler-wallet-core/src/db.ts @@ -1026,6 +1026,11 @@ export interface WireFee { */ closingFee: AmountJson; + /** + * Fees for inter-exchange transfers from P2P payments. + */ + wadFee: AmountJson; + /** * Start date of the fee. */ diff --git a/packages/taler-wallet-core/src/operations/backup/export.ts b/packages/taler-wallet-core/src/operations/backup/export.ts index 75724dca7..05ef66883 100644 --- a/packages/taler-wallet-core/src/operations/backup/export.ts +++ b/packages/taler-wallet-core/src/operations/backup/export.ts @@ -113,9 +113,8 @@ export async function exportBackup( } = {}; await tx.withdrawalGroups.iter().forEachAsync(async (wg) => { - const withdrawalGroups = (withdrawalGroupsByReserve[ - wg.reservePub - ] ??= []); + const withdrawalGroups = (withdrawalGroupsByReserve[wg.reservePub] ??= + []); withdrawalGroups.push({ raw_withdrawal_amount: Amounts.stringify(wg.rawWithdrawalAmount), selected_denoms: wg.denomsSel.selectedDenoms.map((x) => ({ @@ -288,6 +287,7 @@ export async function exportBackup( wireFees.push({ wire_type: x, closing_fee: Amounts.stringify(f.closingFee), + wad_fee: Amounts.stringify(f.wadFee), end_stamp: f.endStamp, sig: f.sig, start_stamp: f.startStamp, diff --git a/packages/taler-wallet-core/src/operations/backup/import.ts b/packages/taler-wallet-core/src/operations/backup/import.ts index 21b10a945..6dafa8c89 100644 --- a/packages/taler-wallet-core/src/operations/backup/import.ts +++ b/packages/taler-wallet-core/src/operations/backup/import.ts @@ -305,6 +305,7 @@ export async function importBackup( sig: fee.sig, startStamp: fee.start_stamp, wireFee: Amounts.parseOrThrow(fee.wire_fee), + wadFee: Amounts.parseOrThrow(fee.wad_fee), }); } await tx.exchangeDetails.put({ diff --git a/packages/taler-wallet-core/src/operations/exchanges.ts b/packages/taler-wallet-core/src/operations/exchanges.ts index c50afc215..9d4a56fff 100644 --- a/packages/taler-wallet-core/src/operations/exchanges.ts +++ b/packages/taler-wallet-core/src/operations/exchanges.ts @@ -266,6 +266,7 @@ async function validateWireInfo( sig: x.sig, startStamp, wireFee: Amounts.parseOrThrow(x.wire_fee), + wadFee: Amounts.parseOrThrow(x.wad_fee), }; let isValid = false; if (ws.insecureTrustExchange) { @@ -451,7 +452,8 @@ export async function downloadTosFromAcceptedFormat( ws: InternalWalletState, baseUrl: string, timeout: Duration, - acceptedFormat?: string[]): Promise { + acceptedFormat?: string[], +): Promise { let tosFound: ExchangeTosDownloadResult | undefined; //Remove this when exchange supports multiple content-type in accept header if (acceptedFormat) @@ -467,7 +469,7 @@ export async function downloadTosFromAcceptedFormat( break; } } - if (tosFound !== undefined) return tosFound + if (tosFound !== undefined) return tosFound; // If none of the specified format was found try text/plain return await downloadExchangeWithTermsOfService( baseUrl, @@ -550,8 +552,12 @@ async function updateExchangeFromUrlImpl( logger.info("finished validating exchange /wire info"); - - const tosDownload = await downloadTosFromAcceptedFormat(ws, baseUrl, timeout, acceptedFormat) + const tosDownload = await downloadTosFromAcceptedFormat( + ws, + baseUrl, + timeout, + acceptedFormat, + ); let recoupGroupId: string | undefined;