wallet-core: address DB FIXMEs

This commit is contained in:
Florian Dold 2022-11-02 17:02:42 +01:00
parent 91e069c742
commit 14456bb942
No known key found for this signature in database
GPG Key ID: D2E4F00F29D02A4B
3 changed files with 100 additions and 58 deletions

View File

@ -46,6 +46,7 @@ import {
TransactionIdStr,
UnblindedSignature,
WireInfo,
HashCodeString,
} from "@gnu-taler/taler-util";
import {
describeContents,
@ -1630,16 +1631,12 @@ export interface TombstoneRecord {
id: string;
}
export interface BalancePerCurrencyRecord {
currency: string;
availableNow: AmountString;
availableExpected: AmountString;
pendingIncoming: AmountString;
pendingOutgoing: AmountString;
export enum PeerPushPaymentInitiationStatus {
/**
* Initiated, but no purse created yet.
*/
Initiated = 10 /* ACTIVE_START */,
PurseCreated = 50 /* DORMANT_START */,
}
/**
@ -1653,7 +1650,8 @@ export interface PeerPushPaymentInitiationRecord {
amount: AmountString;
contractTerms: any;
contractTermsHash: HashCodeString;
/**
* Purse public key. Used as the primary key to look
* up this record.
@ -1679,12 +1677,12 @@ export interface PeerPushPaymentInitiationRecord {
purseExpiration: TalerProtocolTimestamp;
/**
* Did we successfully create the purse with the exchange?
*/
purseCreated: boolean;
timestampCreated: TalerProtocolTimestamp;
/**
* Status of the peer push payment initiation.
*/
status: PeerPushPaymentInitiationStatus;
}
export interface PeerPullPaymentInitiationRecord {
@ -1710,11 +1708,15 @@ export interface PeerPullPaymentInitiationRecord {
pursePriv: string;
/**
* Contract terms for the other party.
*
* FIXME: Put into contract terms store.
* Hash of the contract terms. Also
* used to look up the contract terms in the DB.
*/
contractTerms: PeerContractTerms;
contractTermsHash: string;
/**
* Status of the peer pull payment initiation.
*/
status: OperationStatus;
}
/**
@ -1735,9 +1737,22 @@ export interface PeerPushPaymentIncomingRecord {
timestamp: TalerProtocolTimestamp;
contractTerms: PeerContractTerms;
/**
* Hash of the contract terms. Also
* used to look up the contract terms in the DB.
*/
contractTermsHash: string;
// FIXME: add status etc.
/**
* Status of the peer push payment incoming initiation.
*/
status: OperationStatus;
}
export enum PeerPullPaymentIncomingStatus {
Proposed = 30 /* USER_ATTENTION_START */,
Accepted = 10 /* ACTIVE_START */,
Paid = 50 /* DORMANT_START */,
}
export interface PeerPullPaymentIncomingRecord {
@ -1751,11 +1766,12 @@ export interface PeerPullPaymentIncomingRecord {
timestampCreated: TalerProtocolTimestamp;
paid: boolean;
accepted: boolean;
contractPriv: string;
/**
* Status of the peer push payment incoming initiation.
*/
status: PeerPullPaymentIncomingStatus;
}
/**
@ -2061,13 +2077,6 @@ export const WalletStoresV1 = {
}),
{},
),
balancesPerCurrency: describeStore(
"balancesPerCurrency",
describeContents<BalancePerCurrencyRecord>({
keyPath: "currency",
}),
{},
),
peerPushPaymentIncoming: describeStore(
"peerPushPaymentIncoming",
describeContents<PeerPushPaymentIncomingRecord>({

View File

@ -56,6 +56,7 @@ import {
Logger,
parsePayPullUri,
parsePayPushUri,
PeerContractTerms,
RefreshReason,
strcmp,
TalerProtocolTimestamp,
@ -64,6 +65,10 @@ import {
WalletAccountMergeFlags,
} from "@gnu-taler/taler-util";
import {
OperationStatus,
PeerPullPaymentIncomingStatus,
PeerPushPaymentIncomingRecord,
PeerPushPaymentInitiationStatus,
ReserveRecord,
WalletStoresV1,
WithdrawalGroupStatus,
@ -247,6 +252,7 @@ export async function initiatePeerToPeerPush(
const coinSelRes: PeerCoinSelection | undefined = await ws.db
.mktx((x) => [
x.exchanges,
x.contractTerms,
x.coins,
x.coinAvailability,
x.denominations,
@ -272,16 +278,21 @@ export async function initiatePeerToPeerPush(
await tx.peerPushPaymentInitiations.add({
amount: Amounts.stringify(instructedAmount),
contractPriv: econtractResp.contractPriv,
contractTerms,
contractTermsHash: hContractTerms,
exchangeBaseUrl: sel.exchangeBaseUrl,
mergePriv: mergePair.priv,
mergePub: mergePair.pub,
// FIXME: only set this later!
purseCreated: true,
purseExpiration: purseExpiration,
pursePriv: pursePair.priv,
pursePub: pursePair.pub,
timestampCreated: TalerProtocolTimestamp.now(),
// FIXME: Only set the later when the purse is actually created!
status: PeerPushPaymentInitiationStatus.PurseCreated,
});
await tx.contractTerms.put({
h: hContractTerms,
contractTermsRaw: contractTerms,
});
return sel;
@ -403,8 +414,12 @@ export async function checkPeerPushPayment(
const peerPushPaymentIncomingId = encodeCrock(getRandomBytes(32));
const contractTermsHash = ContractTermsUtil.hashContractTerms(
dec.contractTerms,
);
await ws.db
.mktx((x) => [x.peerPushPaymentIncoming])
.mktx((x) => [x.contractTerms, x.peerPushPaymentIncoming])
.runReadWrite(async (tx) => {
await tx.peerPushPaymentIncoming.add({
peerPushPaymentIncomingId,
@ -413,7 +428,13 @@ export async function checkPeerPushPayment(
mergePriv: dec.mergePriv,
pursePub: pursePub,
timestamp: TalerProtocolTimestamp.now(),
contractTerms: dec.contractTerms,
contractTermsHash,
status: OperationStatus.Finished,
});
await tx.contractTerms.put({
h: contractTermsHash,
contractTermsRaw: dec.contractTerms,
});
});
@ -485,10 +506,21 @@ export async function acceptPeerPushPayment(
ws: InternalWalletState,
req: AcceptPeerPushPaymentRequest,
): Promise<AcceptPeerPushPaymentResponse> {
const peerInc = await ws.db
.mktx((x) => [x.peerPushPaymentIncoming])
let peerInc: PeerPushPaymentIncomingRecord | undefined;
let contractTerms: PeerContractTerms | undefined;
await ws.db
.mktx((x) => [x.contractTerms, x.peerPushPaymentIncoming])
.runReadOnly(async (tx) => {
return tx.peerPushPaymentIncoming.get(req.peerPushPaymentIncomingId);
peerInc = await tx.peerPushPaymentIncoming.get(
req.peerPushPaymentIncomingId,
);
if (!peerInc) {
return;
}
const ctRec = await tx.contractTerms.get(peerInc.contractTermsHash);
if (ctRec) {
contractTerms = ctRec.contractTermsRaw;
}
});
if (!peerInc) {
@ -497,9 +529,11 @@ export async function acceptPeerPushPayment(
);
}
checkDbInvariant(!!contractTerms);
await updateExchangeFromUrl(ws, peerInc.exchangeBaseUrl);
const amount = Amounts.parseOrThrow(peerInc.contractTerms.amount);
const amount = Amounts.parseOrThrow(contractTerms.amount);
const mergeReserveInfo = await getMergeReserveInfo(ws, {
exchangeBaseUrl: peerInc.exchangeBaseUrl,
@ -513,14 +547,12 @@ export async function acceptPeerPushPayment(
);
const sigRes = await ws.cryptoApi.signPurseMerge({
contractTermsHash: ContractTermsUtil.hashContractTerms(
peerInc.contractTerms,
),
contractTermsHash: ContractTermsUtil.hashContractTerms(contractTerms),
flags: WalletAccountMergeFlags.MergeFullyPaidPurse,
mergePriv: peerInc.mergePriv,
mergeTimestamp: mergeTimestamp,
purseAmount: Amounts.stringify(amount),
purseExpiration: peerInc.contractTerms.purse_expiration,
purseExpiration: contractTerms.purse_expiration,
purseFee: Amounts.stringify(Amounts.getZero(amount.currency)),
pursePub: peerInc.pursePub,
reservePayto,
@ -549,7 +581,7 @@ export async function acceptPeerPushPayment(
amount,
wgInfo: {
withdrawalType: WithdrawalRecordType.PeerPushCredit,
contractTerms: peerInc.contractTerms,
contractTerms,
},
exchangeBaseUrl: peerInc.exchangeBaseUrl,
reserveStatus: WithdrawalGroupStatus.QueryingStatus,
@ -567,9 +599,6 @@ export async function acceptPeerPushPayment(
};
}
/**
* FIXME: Bad name!
*/
export async function acceptPeerPullPayment(
ws: InternalWalletState,
req: AcceptPeerPullPaymentRequest,
@ -619,7 +648,7 @@ export async function acceptPeerPullPayment(
if (!pi) {
throw Error();
}
pi.accepted = true;
pi.status = PeerPullPaymentIncomingStatus.Accepted;
await tx.peerPullPaymentIncoming.put(pi);
return sel;
@ -711,8 +740,7 @@ export async function checkPeerPullPayment(
pursePub: pursePub,
timestampCreated: TalerProtocolTimestamp.now(),
contractTerms: dec.contractTerms,
paid: false,
accepted: false,
status: PeerPullPaymentIncomingStatus.Proposed,
});
});
@ -726,7 +754,7 @@ export async function checkPeerPullPayment(
/**
* Initiate a peer pull payment.
*/
export async function initiatePeerRequestForPay(
export async function initiatePeerPullPayment(
ws: InternalWalletState,
req: InitiatePeerPullPaymentRequest,
): Promise<InitiatePeerPullPaymentResponse> {
@ -786,14 +814,19 @@ export async function initiatePeerRequestForPay(
});
await ws.db
.mktx((x) => [x.peerPullPaymentInitiations])
.mktx((x) => [x.peerPullPaymentInitiations, x.contractTerms])
.runReadWrite(async (tx) => {
await tx.peerPullPaymentInitiations.put({
amount: req.amount,
contractTerms,
contractTermsHash: hContractTerms,
exchangeBaseUrl: req.exchangeBaseUrl,
pursePriv: pursePair.priv,
pursePub: pursePair.pub,
status: OperationStatus.Finished,
});
await tx.contractTerms.put({
contractTermsRaw: contractTerms,
h: hContractTerms,
});
});

View File

@ -184,7 +184,7 @@ import {
acceptPeerPushPayment,
checkPeerPullPayment,
checkPeerPushPayment,
initiatePeerRequestForPay,
initiatePeerPullPayment,
initiatePeerToPeerPush,
} from "./operations/pay-peer.js";
import { getPendingOperations } from "./operations/pending.js";
@ -1354,7 +1354,7 @@ async function dispatchRequestInternal<Op extends WalletApiOperation>(
}
case WalletApiOperation.InitiatePeerPullPayment: {
const req = codecForInitiatePeerPullPaymentRequest().decode(payload);
return await initiatePeerRequestForPay(ws, req);
return await initiatePeerPullPayment(ws, req);
}
case WalletApiOperation.CheckPeerPullPayment: {
const req = codecForCheckPeerPullPaymentRequest().decode(payload);