DB schema cleanup
This commit is contained in:
parent
a09359bd39
commit
4c41e70565
@ -788,6 +788,33 @@ export interface MakeSyncSignatureRequest {
|
|||||||
newHash: string;
|
newHash: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Planchet for a coin during refresh.
|
||||||
|
*/
|
||||||
|
export interface RefreshPlanchetInfo {
|
||||||
|
/**
|
||||||
|
* Public key for the coin.
|
||||||
|
*/
|
||||||
|
publicKey: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Private key for the coin.
|
||||||
|
*/
|
||||||
|
privateKey: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Blinded public key.
|
||||||
|
*/
|
||||||
|
coinEv: string;
|
||||||
|
|
||||||
|
coinEvHash: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Blinding key used.
|
||||||
|
*/
|
||||||
|
blindingKey: string;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Strategy for loading recovery information.
|
* Strategy for loading recovery information.
|
||||||
*/
|
*/
|
||||||
|
@ -30,12 +30,11 @@
|
|||||||
import {
|
import {
|
||||||
CoinRecord,
|
CoinRecord,
|
||||||
DenominationRecord,
|
DenominationRecord,
|
||||||
RefreshPlanchet,
|
|
||||||
WireFee,
|
WireFee,
|
||||||
CoinSourceType,
|
CoinSourceType,
|
||||||
} from "../../db.js";
|
} from "../../db.js";
|
||||||
|
|
||||||
import { CoinDepositPermission, RecoupRequest } from "@gnu-taler/taler-util";
|
import { CoinDepositPermission, RecoupRequest, RefreshPlanchetInfo } from "@gnu-taler/taler-util";
|
||||||
// FIXME: These types should be internal to the wallet!
|
// FIXME: These types should be internal to the wallet!
|
||||||
import {
|
import {
|
||||||
BenchmarkResult,
|
BenchmarkResult,
|
||||||
@ -442,7 +441,7 @@ export class CryptoImplementation {
|
|||||||
const transferPubs: string[] = [];
|
const transferPubs: string[] = [];
|
||||||
const transferPrivs: string[] = [];
|
const transferPrivs: string[] = [];
|
||||||
|
|
||||||
const planchetsForGammas: RefreshPlanchet[][] = [];
|
const planchetsForGammas: RefreshPlanchetInfo[][] = [];
|
||||||
|
|
||||||
for (let i = 0; i < kappa; i++) {
|
for (let i = 0; i < kappa; i++) {
|
||||||
const transferKeyPair = setupRefreshTransferPub(
|
const transferKeyPair = setupRefreshTransferPub(
|
||||||
@ -464,7 +463,7 @@ export class CryptoImplementation {
|
|||||||
sessionHc.update(decodeCrock(meltCoinPub));
|
sessionHc.update(decodeCrock(meltCoinPub));
|
||||||
sessionHc.update(amountToBuffer(valueWithFee));
|
sessionHc.update(amountToBuffer(valueWithFee));
|
||||||
for (let i = 0; i < kappa; i++) {
|
for (let i = 0; i < kappa; i++) {
|
||||||
const planchets: RefreshPlanchet[] = [];
|
const planchets: RefreshPlanchetInfo[] = [];
|
||||||
for (let j = 0; j < newCoinDenoms.length; j++) {
|
for (let j = 0; j < newCoinDenoms.length; j++) {
|
||||||
const denomSel = newCoinDenoms[j];
|
const denomSel = newCoinDenoms[j];
|
||||||
for (let k = 0; k < denomSel.count; k++) {
|
for (let k = 0; k < denomSel.count; k++) {
|
||||||
@ -482,7 +481,7 @@ export class CryptoImplementation {
|
|||||||
const pubHash = hash(coinPub);
|
const pubHash = hash(coinPub);
|
||||||
const denomPub = decodeCrock(denomSel.denomPub);
|
const denomPub = decodeCrock(denomSel.denomPub);
|
||||||
const ev = rsaBlind(pubHash, blindingFactor, denomPub);
|
const ev = rsaBlind(pubHash, blindingFactor, denomPub);
|
||||||
const planchet: RefreshPlanchet = {
|
const planchet: RefreshPlanchetInfo = {
|
||||||
blindingKey: encodeCrock(blindingFactor),
|
blindingKey: encodeCrock(blindingFactor),
|
||||||
coinEv: encodeCrock(ev),
|
coinEv: encodeCrock(ev),
|
||||||
privateKey: encodeCrock(coinPriv),
|
privateKey: encodeCrock(coinPriv),
|
||||||
|
@ -134,8 +134,27 @@ export async function openTalerDatabase(
|
|||||||
});
|
});
|
||||||
|
|
||||||
if (currentMainVersion !== TALER_DB_NAME) {
|
if (currentMainVersion !== TALER_DB_NAME) {
|
||||||
// In the future, the migration logic will be implemented here.
|
switch (currentMainVersion) {
|
||||||
throw Error(`migration from database ${currentMainVersion} not supported`);
|
case "taler-wallet-main-v2": {
|
||||||
|
// We consider this a pre-release
|
||||||
|
// development version, no migration is done.
|
||||||
|
await metaDb
|
||||||
|
.mktx((x) => ({
|
||||||
|
metaConfig: x.metaConfig,
|
||||||
|
}))
|
||||||
|
.runReadWrite(async (tx) => {
|
||||||
|
await tx.metaConfig.put({
|
||||||
|
key: CURRENT_DB_CONFIG_KEY,
|
||||||
|
value: TALER_DB_NAME,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
throw Error(
|
||||||
|
`migration from database ${currentMainVersion} not supported`,
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const mainDbHandle = await openDatabase(
|
const mainDbHandle = await openDatabase(
|
||||||
|
@ -46,7 +46,7 @@ import { PayCoinSelection } from "./util/coinSelection.js";
|
|||||||
* for all previous versions must be written, which should be
|
* for all previous versions must be written, which should be
|
||||||
* avoided.
|
* avoided.
|
||||||
*/
|
*/
|
||||||
export const TALER_DB_NAME = "taler-wallet-main-v2";
|
export const TALER_DB_NAME = "taler-wallet-main-v3";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Name of the metadata database. This database is used
|
* Name of the metadata database. This database is used
|
||||||
@ -283,7 +283,7 @@ export interface ExchangeTrustRecord {
|
|||||||
/**
|
/**
|
||||||
* Status of a denomination.
|
* Status of a denomination.
|
||||||
*/
|
*/
|
||||||
export enum DenominationStatus {
|
export enum DenominationVerificationStatus {
|
||||||
/**
|
/**
|
||||||
* Verification was delayed.
|
* Verification was delayed.
|
||||||
*/
|
*/
|
||||||
@ -366,10 +366,8 @@ export interface DenominationRecord {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Did we verify the signature on the denomination?
|
* Did we verify the signature on the denomination?
|
||||||
*
|
|
||||||
* FIXME: Rename to "verificationStatus"?
|
|
||||||
*/
|
*/
|
||||||
status: DenominationStatus;
|
verificationStatus: DenominationVerificationStatus;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Was this denomination still offered by the exchange the last time
|
* Was this denomination still offered by the exchange the last time
|
||||||
@ -590,35 +588,6 @@ export interface PlanchetRecord {
|
|||||||
isFromTip: boolean;
|
isFromTip: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Planchet for a coin during refresh.
|
|
||||||
*
|
|
||||||
* FIXME: Not used in DB?
|
|
||||||
*/
|
|
||||||
export interface RefreshPlanchet {
|
|
||||||
/**
|
|
||||||
* Public key for the coin.
|
|
||||||
*/
|
|
||||||
publicKey: string;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Private key for the coin.
|
|
||||||
*/
|
|
||||||
privateKey: string;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Blinded public key.
|
|
||||||
*/
|
|
||||||
coinEv: string;
|
|
||||||
|
|
||||||
coinEvHash: string;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Blinding key used.
|
|
||||||
*/
|
|
||||||
blindingKey: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Status of a coin.
|
* Status of a coin.
|
||||||
*/
|
*/
|
||||||
@ -1319,21 +1288,6 @@ export interface WalletBackupConfState {
|
|||||||
lastBackupNonce?: string;
|
lastBackupNonce?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* FIXME: Eliminate this in favor of DenomSelectionState.
|
|
||||||
*/
|
|
||||||
export interface DenominationSelectionInfo {
|
|
||||||
totalCoinValue: AmountJson;
|
|
||||||
totalWithdrawCost: AmountJson;
|
|
||||||
selectedDenoms: {
|
|
||||||
/**
|
|
||||||
* How many times do we withdraw this denomination?
|
|
||||||
*/
|
|
||||||
count: number;
|
|
||||||
denom: DenominationRecord;
|
|
||||||
}[];
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Selected denominations withn some extra info.
|
* Selected denominations withn some extra info.
|
||||||
*/
|
*/
|
||||||
|
@ -31,7 +31,7 @@ import {
|
|||||||
import {
|
import {
|
||||||
WalletContractData,
|
WalletContractData,
|
||||||
DenomSelectionState,
|
DenomSelectionState,
|
||||||
DenominationStatus,
|
DenominationVerificationStatus,
|
||||||
CoinSource,
|
CoinSource,
|
||||||
CoinSourceType,
|
CoinSourceType,
|
||||||
CoinStatus,
|
CoinStatus,
|
||||||
@ -359,7 +359,7 @@ export async function importBackup(
|
|||||||
stampExpireLegal: backupDenomination.stamp_expire_legal,
|
stampExpireLegal: backupDenomination.stamp_expire_legal,
|
||||||
stampExpireWithdraw: backupDenomination.stamp_expire_withdraw,
|
stampExpireWithdraw: backupDenomination.stamp_expire_withdraw,
|
||||||
stampStart: backupDenomination.stamp_start,
|
stampStart: backupDenomination.stamp_start,
|
||||||
status: DenominationStatus.VerifiedGood,
|
verificationStatus: DenominationVerificationStatus.VerifiedGood,
|
||||||
value: Amounts.parseOrThrow(backupDenomination.value),
|
value: Amounts.parseOrThrow(backupDenomination.value),
|
||||||
listIssueDate: backupDenomination.list_issue_date,
|
listIssueDate: backupDenomination.list_issue_date,
|
||||||
});
|
});
|
||||||
|
@ -44,7 +44,7 @@ import { decodeCrock, encodeCrock, hash } from "../crypto/talerCrypto.js";
|
|||||||
import { CryptoApi } from "../crypto/workers/cryptoApi.js";
|
import { CryptoApi } from "../crypto/workers/cryptoApi.js";
|
||||||
import {
|
import {
|
||||||
DenominationRecord,
|
DenominationRecord,
|
||||||
DenominationStatus,
|
DenominationVerificationStatus,
|
||||||
ExchangeDetailsRecord,
|
ExchangeDetailsRecord,
|
||||||
ExchangeRecord,
|
ExchangeRecord,
|
||||||
WalletStoresV1,
|
WalletStoresV1,
|
||||||
@ -95,7 +95,7 @@ function denominationRecordFromKeys(
|
|||||||
stampExpireLegal: denomIn.stamp_expire_legal,
|
stampExpireLegal: denomIn.stamp_expire_legal,
|
||||||
stampExpireWithdraw: denomIn.stamp_expire_withdraw,
|
stampExpireWithdraw: denomIn.stamp_expire_withdraw,
|
||||||
stampStart: denomIn.stamp_start,
|
stampStart: denomIn.stamp_start,
|
||||||
status: DenominationStatus.Unverified,
|
verificationStatus: DenominationVerificationStatus.Unverified,
|
||||||
value: Amounts.parseOrThrow(denomIn.value),
|
value: Amounts.parseOrThrow(denomIn.value),
|
||||||
listIssueDate,
|
listIssueDate,
|
||||||
};
|
};
|
||||||
|
@ -22,7 +22,6 @@ import {
|
|||||||
DenominationRecord,
|
DenominationRecord,
|
||||||
RefreshCoinStatus,
|
RefreshCoinStatus,
|
||||||
RefreshGroupRecord,
|
RefreshGroupRecord,
|
||||||
RefreshPlanchet,
|
|
||||||
WalletStoresV1,
|
WalletStoresV1,
|
||||||
} from "../db.js";
|
} from "../db.js";
|
||||||
import {
|
import {
|
||||||
@ -32,6 +31,7 @@ import {
|
|||||||
fnutil,
|
fnutil,
|
||||||
NotificationType,
|
NotificationType,
|
||||||
RefreshGroupId,
|
RefreshGroupId,
|
||||||
|
RefreshPlanchetInfo,
|
||||||
RefreshReason,
|
RefreshReason,
|
||||||
stringifyTimestamp,
|
stringifyTimestamp,
|
||||||
TalerErrorDetails,
|
TalerErrorDetails,
|
||||||
@ -534,7 +534,7 @@ async function refreshReveal(
|
|||||||
throw Error("refresh index error");
|
throw Error("refresh index error");
|
||||||
}
|
}
|
||||||
|
|
||||||
const evs = planchets.map((x: RefreshPlanchet) => x.coinEv);
|
const evs = planchets.map((x: RefreshPlanchetInfo) => x.coinEv);
|
||||||
const newDenomsFlat: string[] = [];
|
const newDenomsFlat: string[] = [];
|
||||||
const linkSigs: string[] = [];
|
const linkSigs: string[] = [];
|
||||||
|
|
||||||
|
@ -16,7 +16,7 @@
|
|||||||
|
|
||||||
import { Amounts } from "@gnu-taler/taler-util";
|
import { Amounts } from "@gnu-taler/taler-util";
|
||||||
import test from "ava";
|
import test from "ava";
|
||||||
import { DenominationRecord, DenominationStatus } from "../db.js";
|
import { DenominationRecord, DenominationVerificationStatus } from "../db.js";
|
||||||
import { selectWithdrawalDenominations } from "./withdraw.js";
|
import { selectWithdrawalDenominations } from "./withdraw.js";
|
||||||
|
|
||||||
test("withdrawal selection bug repro", (t) => {
|
test("withdrawal selection bug repro", (t) => {
|
||||||
@ -70,7 +70,7 @@ test("withdrawal selection bug repro", (t) => {
|
|||||||
stampStart: {
|
stampStart: {
|
||||||
t_ms: 1585229388000,
|
t_ms: 1585229388000,
|
||||||
},
|
},
|
||||||
status: DenominationStatus.Unverified,
|
verificationStatus: DenominationVerificationStatus.Unverified,
|
||||||
value: {
|
value: {
|
||||||
currency: "KUDOS",
|
currency: "KUDOS",
|
||||||
fraction: 0,
|
fraction: 0,
|
||||||
@ -121,7 +121,7 @@ test("withdrawal selection bug repro", (t) => {
|
|||||||
stampStart: {
|
stampStart: {
|
||||||
t_ms: 1585229388000,
|
t_ms: 1585229388000,
|
||||||
},
|
},
|
||||||
status: DenominationStatus.Unverified,
|
verificationStatus: DenominationVerificationStatus.Unverified,
|
||||||
value: {
|
value: {
|
||||||
currency: "KUDOS",
|
currency: "KUDOS",
|
||||||
fraction: 0,
|
fraction: 0,
|
||||||
@ -172,7 +172,7 @@ test("withdrawal selection bug repro", (t) => {
|
|||||||
stampStart: {
|
stampStart: {
|
||||||
t_ms: 1585229388000,
|
t_ms: 1585229388000,
|
||||||
},
|
},
|
||||||
status: DenominationStatus.Unverified,
|
verificationStatus: DenominationVerificationStatus.Unverified,
|
||||||
value: {
|
value: {
|
||||||
currency: "KUDOS",
|
currency: "KUDOS",
|
||||||
fraction: 0,
|
fraction: 0,
|
||||||
@ -223,7 +223,7 @@ test("withdrawal selection bug repro", (t) => {
|
|||||||
stampStart: {
|
stampStart: {
|
||||||
t_ms: 1585229388000,
|
t_ms: 1585229388000,
|
||||||
},
|
},
|
||||||
status: DenominationStatus.Unverified,
|
verificationStatus: DenominationVerificationStatus.Unverified,
|
||||||
value: {
|
value: {
|
||||||
currency: "KUDOS",
|
currency: "KUDOS",
|
||||||
fraction: 0,
|
fraction: 0,
|
||||||
@ -274,7 +274,7 @@ test("withdrawal selection bug repro", (t) => {
|
|||||||
stampStart: {
|
stampStart: {
|
||||||
t_ms: 1585229388000,
|
t_ms: 1585229388000,
|
||||||
},
|
},
|
||||||
status: DenominationStatus.Unverified,
|
verificationStatus: DenominationVerificationStatus.Unverified,
|
||||||
value: {
|
value: {
|
||||||
currency: "KUDOS",
|
currency: "KUDOS",
|
||||||
fraction: 10000000,
|
fraction: 10000000,
|
||||||
@ -325,7 +325,7 @@ test("withdrawal selection bug repro", (t) => {
|
|||||||
stampStart: {
|
stampStart: {
|
||||||
t_ms: 1585229388000,
|
t_ms: 1585229388000,
|
||||||
},
|
},
|
||||||
status: DenominationStatus.Unverified,
|
verificationStatus: DenominationVerificationStatus.Unverified,
|
||||||
value: {
|
value: {
|
||||||
currency: "KUDOS",
|
currency: "KUDOS",
|
||||||
fraction: 0,
|
fraction: 0,
|
||||||
|
@ -47,8 +47,7 @@ import {
|
|||||||
CoinSourceType,
|
CoinSourceType,
|
||||||
CoinStatus,
|
CoinStatus,
|
||||||
DenominationRecord,
|
DenominationRecord,
|
||||||
DenominationSelectionInfo,
|
DenominationVerificationStatus,
|
||||||
DenominationStatus,
|
|
||||||
DenomSelectionState,
|
DenomSelectionState,
|
||||||
ExchangeDetailsRecord,
|
ExchangeDetailsRecord,
|
||||||
ExchangeRecord,
|
ExchangeRecord,
|
||||||
@ -73,6 +72,21 @@ import {
|
|||||||
*/
|
*/
|
||||||
const logger = new Logger("withdraw.ts");
|
const logger = new Logger("withdraw.ts");
|
||||||
|
|
||||||
|
/**
|
||||||
|
* FIXME: Eliminate this in favor of DenomSelectionState.
|
||||||
|
*/
|
||||||
|
interface DenominationSelectionInfo {
|
||||||
|
totalCoinValue: AmountJson;
|
||||||
|
totalWithdrawCost: AmountJson;
|
||||||
|
selectedDenoms: {
|
||||||
|
/**
|
||||||
|
* How many times do we withdraw this denomination?
|
||||||
|
*/
|
||||||
|
count: number;
|
||||||
|
denom: DenominationRecord;
|
||||||
|
}[];
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Information about what will happen when creating a reserve.
|
* Information about what will happen when creating a reserve.
|
||||||
*
|
*
|
||||||
@ -231,9 +245,13 @@ export function selectWithdrawalDenominations(
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (logger.shouldLogTrace()) {
|
if (logger.shouldLogTrace()) {
|
||||||
logger.trace(`selected withdrawal denoms for ${Amounts.stringify(totalCoinValue)}`);
|
logger.trace(
|
||||||
|
`selected withdrawal denoms for ${Amounts.stringify(totalCoinValue)}`,
|
||||||
|
);
|
||||||
for (const sd of selectedDenoms) {
|
for (const sd of selectedDenoms) {
|
||||||
logger.trace(`denom_pub_hash=${sd.denom.denomPubHash}, count=${sd.count}`);
|
logger.trace(
|
||||||
|
`denom_pub_hash=${sd.denom.denomPubHash}, count=${sd.count}`,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
logger.trace("(end of withdrawal denom list)");
|
logger.trace("(end of withdrawal denom list)");
|
||||||
}
|
}
|
||||||
@ -314,7 +332,9 @@ export async function getCandidateWithdrawalDenoms(
|
|||||||
return await ws.db
|
return await ws.db
|
||||||
.mktx((x) => ({ denominations: x.denominations }))
|
.mktx((x) => ({ denominations: x.denominations }))
|
||||||
.runReadOnly(async (tx) => {
|
.runReadOnly(async (tx) => {
|
||||||
const allDenoms = await tx.denominations.indexes.byExchangeBaseUrl.getAll(exchangeBaseUrl);
|
const allDenoms = await tx.denominations.indexes.byExchangeBaseUrl.getAll(
|
||||||
|
exchangeBaseUrl,
|
||||||
|
);
|
||||||
return allDenoms.filter(isWithdrawableDenom);
|
return allDenoms.filter(isWithdrawableDenom);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -708,7 +728,7 @@ export async function updateWithdrawalDenoms(
|
|||||||
batchIdx++, current++
|
batchIdx++, current++
|
||||||
) {
|
) {
|
||||||
const denom = denominations[current];
|
const denom = denominations[current];
|
||||||
if (denom.status === DenominationStatus.Unverified) {
|
if (denom.verificationStatus === DenominationVerificationStatus.Unverified) {
|
||||||
logger.trace(
|
logger.trace(
|
||||||
`Validating denomination (${current + 1}/${
|
`Validating denomination (${current + 1}/${
|
||||||
denominations.length
|
denominations.length
|
||||||
@ -723,9 +743,9 @@ export async function updateWithdrawalDenoms(
|
|||||||
logger.warn(
|
logger.warn(
|
||||||
`Signature check for denomination h=${denom.denomPubHash} failed`,
|
`Signature check for denomination h=${denom.denomPubHash} failed`,
|
||||||
);
|
);
|
||||||
denom.status = DenominationStatus.VerifiedBad;
|
denom.verificationStatus = DenominationVerificationStatus.VerifiedBad;
|
||||||
} else {
|
} else {
|
||||||
denom.status = DenominationStatus.VerifiedGood;
|
denom.verificationStatus = DenominationVerificationStatus.VerifiedGood;
|
||||||
}
|
}
|
||||||
updatedDenominations.push(denom);
|
updatedDenominations.push(denom);
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user