remove deprecated auditor trust management

This commit is contained in:
Florian Dold 2023-09-06 18:35:43 +02:00
parent 6affe04fe6
commit cd9c3a143b
No known key found for this signature in database
GPG Key ID: D2E4F00F29D02A4B
9 changed files with 51 additions and 245 deletions

View File

@ -1464,22 +1464,11 @@ export interface ExchangeWithdrawalDetails {
*/
selectedDenoms: DenomSelectionState;
/**
* Does the wallet know about an auditor for
* the exchange that the reserve.
*/
isAudited: boolean;
/**
* Did the user already accept the current terms of service for the exchange?
*/
termsOfServiceAccepted: boolean;
/**
* The exchange is trusted directly.
*/
isTrusted: boolean;
/**
* The earliest deposit expiration of the selected coins.
*/

View File

@ -139,8 +139,6 @@ export const CURRENT_DB_CONFIG_KEY = "currentMainDbName";
*/
export const WALLET_DB_MINOR_VERSION = 10;
/**
* Format of the operation status code: xyznnn
*
@ -293,61 +291,6 @@ export interface ReserveBankInfo {
timestampBankConfirmed: TalerPreciseTimestamp | undefined;
}
/**
* Record that indicates the wallet trusts
* a particular auditor.
*/
export interface AuditorTrustRecord {
/**
* Currency that we trust this auditor for.
*/
currency: string;
/**
* Base URL of the auditor.
*/
auditorBaseUrl: string;
/**
* Public key of the auditor.
*/
auditorPub: string;
/**
* UIDs for the operation of adding this auditor
* as a trusted auditor.
*
* (Used for backup/sync merging and tombstones.)
*/
uids: string[];
}
/**
* Record to indicate trust for a particular exchange.
*/
export interface ExchangeTrustRecord {
/**
* Currency that we trust this exchange for.
*/
currency: string;
/**
* Canonicalized exchange base URL.
*/
exchangeBaseUrl: string;
/**
* Master public key of the exchange.
*/
exchangeMasterPub: string;
/**
* UIDs for the operation of adding this exchange
* as trusted.
*/
uids: string[];
}
/**
* Status of a denomination.
*/
@ -2451,30 +2394,6 @@ export const WalletStoresV1 = {
describeContents<ConfigRecord>({ keyPath: "key" }),
{},
),
auditorTrust: describeStore(
"auditorTrust",
describeContents<AuditorTrustRecord>({
keyPath: ["currency", "auditorBaseUrl"],
}),
{
byAuditorPub: describeIndex("byAuditorPub", "auditorPub"),
byUid: describeIndex("byUid", "uids", {
multiEntry: true,
}),
},
),
exchangeTrust: describeStore(
"exchangeTrust",
describeContents<ExchangeTrustRecord>({
keyPath: ["currency", "exchangeBaseUrl"],
}),
{
byExchangeMasterPub: describeIndex(
"byExchangeMasterPub",
"exchangeMasterPub",
),
},
),
denominations: describeStore(
"denominations",
describeContents<DenominationRecord>({

View File

@ -107,10 +107,6 @@ export interface ExchangeOperations {
}>,
exchangeBaseUrl: string,
): Promise<ExchangeDetailsRecord | undefined>;
getExchangeTrust(
ws: InternalWalletState,
exchangeInfo: ExchangeEntryRecord,
): Promise<TrustInfo>;
updateExchangeFromUrl(
ws: InternalWalletState,
baseUrl: string,

View File

@ -281,7 +281,7 @@ export async function getAcceptableExchangeBaseUrls(
const acceptableExchangeUrls = new Set<string>();
const depositableExchangeUrls = new Set<string>();
await ws.db
.mktx((x) => [x.exchanges, x.exchangeDetails, x.auditorTrust])
.mktx((x) => [x.exchanges, x.exchangeDetails])
.runReadOnly(async (tx) => {
// FIXME: We should have a DB index to look up all exchanges
// for a particular auditor ...

View File

@ -972,54 +972,3 @@ export async function getExchangePaytoUri(
)}`,
);
}
/**
* Check if and how an exchange is trusted and/or audited.
*/
export async function getExchangeTrust(
ws: InternalWalletState,
exchangeInfo: ExchangeEntryRecord,
): Promise<TrustInfo> {
let isTrusted = false;
let isAudited = false;
return await ws.db
.mktx((x) => [
x.exchanges,
x.exchangeDetails,
x.exchangeTrust,
x.auditorTrust,
])
.runReadOnly(async (tx) => {
const exchangeDetails = await getExchangeDetails(
tx,
exchangeInfo.baseUrl,
);
if (!exchangeDetails) {
throw Error(`exchange ${exchangeInfo.baseUrl} details not available`);
}
const exchangeTrustRecord =
await tx.exchangeTrust.indexes.byExchangeMasterPub.get(
exchangeDetails.masterPublicKey,
);
if (
exchangeTrustRecord &&
exchangeTrustRecord.uids.length > 0 &&
exchangeTrustRecord.currency === exchangeDetails.currency
) {
isTrusted = true;
}
for (const auditor of exchangeDetails.auditors) {
const auditorTrustRecord =
await tx.auditorTrust.indexes.byAuditorPub.get(auditor.auditor_pub);
if (auditorTrustRecord && auditorTrustRecord.uids.length > 0) {
isAudited = true;
break;
}
}
return { isTrusted, isAudited };
});
}

View File

@ -465,7 +465,6 @@ async function handlePendingMerge(
x.reserves,
x.exchanges,
x.exchangeDetails,
x.exchangeTrust,
])
.runReadWrite(async (tx) => {
const peerInc = await tx.peerPushPaymentIncoming.get(

View File

@ -119,7 +119,6 @@ import {
import {
getExchangeDetails,
getExchangePaytoUri,
getExchangeTrust,
updateExchangeFromUrl,
} from "./exchanges.js";
import {
@ -722,7 +721,9 @@ interface WithdrawalBatchResult {
batchResp: ExchangeWithdrawBatchResponse;
}
enum AmlStatus {
normal= 0, pending = 1, fronzen = 2,
normal = 0,
pending = 1,
fronzen = 2,
}
async function handleKycRequired(
@ -769,7 +770,9 @@ async function handleKycRequired(
const kycStatus = await kycStatusRes.json();
logger.info(`kyc status: ${j2s(kycStatus)}`);
kycUrl = kycStatus.kyc_url;
} else if (kycStatusRes.status === HttpStatusCode.UnavailableForLegalReasons) {
} else if (
kycStatusRes.status === HttpStatusCode.UnavailableForLegalReasons
) {
const kycStatus = await kycStatusRes.json();
logger.info(`aml status: ${j2s(kycStatus)}`);
amlStatus = kycStatus.aml_status;
@ -805,11 +808,15 @@ async function handleKycRequired(
requirementRow: uuidResp.requirement_row,
};
wg2.kycUrl = kycUrl;
wg2.status = amlStatus === AmlStatus.normal || amlStatus === undefined ? WithdrawalGroupStatus.PendingKyc :
amlStatus === AmlStatus.pending ? WithdrawalGroupStatus.PendingAml :
amlStatus === AmlStatus.fronzen ? WithdrawalGroupStatus.SuspendedAml :
assertUnreachable(amlStatus);
wg2.status =
amlStatus === AmlStatus.normal || amlStatus === undefined
? WithdrawalGroupStatus.PendingKyc
: amlStatus === AmlStatus.pending
? WithdrawalGroupStatus.PendingAml
: amlStatus === AmlStatus.fronzen
? WithdrawalGroupStatus.SuspendedAml
: assertUnreachable(amlStatus);
await tx.withdrawalGroups.put(wg2);
const newTxState = computeWithdrawalTransactionStatus(wg2);
return {
@ -919,31 +926,31 @@ async function processPlanchetExchangeBatchRequest(
// FIXME: handle individual error codes better!
const reqUrl = new URL(
`reserves/${withdrawalGroup.reservePub}/batch-withdraw`,
withdrawalGroup.exchangeBaseUrl,
).href;
const reqUrl = new URL(
`reserves/${withdrawalGroup.reservePub}/batch-withdraw`,
withdrawalGroup.exchangeBaseUrl,
).href;
try {
const resp = await ws.http.postJson(reqUrl, batchReq);
if (resp.status === HttpStatusCode.UnavailableForLegalReasons) {
await handleKycRequired(ws, withdrawalGroup, resp, 0, requestCoinIdxs);
}
const r = await readSuccessResponseJsonOrThrow(
resp,
codecForWithdrawBatchResponse(),
);
return {
coinIdxs: requestCoinIdxs,
batchResp: r,
};
} catch (e) {
await storeCoinError(e, requestCoinIdxs[0]);
return {
batchResp: { ev_sigs: [] },
coinIdxs: [],
};
try {
const resp = await ws.http.postJson(reqUrl, batchReq);
if (resp.status === HttpStatusCode.UnavailableForLegalReasons) {
await handleKycRequired(ws, withdrawalGroup, resp, 0, requestCoinIdxs);
}
const r = await readSuccessResponseJsonOrThrow(
resp,
codecForWithdrawBatchResponse(),
);
return {
coinIdxs: requestCoinIdxs,
batchResp: r,
};
} catch (e) {
await storeCoinError(e, requestCoinIdxs[0]);
return {
batchResp: { ev_sigs: [] },
coinIdxs: [],
};
}
}
async function processPlanchetVerifyAndStoreCoin(
@ -1410,10 +1417,12 @@ async function processWithdrawalGroupPendingKyc(
logger.info(`kyc status: ${j2s(kycStatus)}`);
// FIXME: do we need to update the KYC url, or does it always stay constant?
return { ready: false };
} else if (kycStatusRes.status === HttpStatusCode.UnavailableForLegalReasons) {
} else if (
kycStatusRes.status === HttpStatusCode.UnavailableForLegalReasons
) {
const kycStatus = await kycStatusRes.json();
logger.info(`aml status: ${j2s(kycStatus)}`);
return {ready : false}
return { ready: false };
} else {
throw Error(
`unexpected response from kyc-check (${kycStatusRes.status})`,
@ -1709,11 +1718,6 @@ export async function getExchangeWithdrawalInfo(
exchangeWireAccounts.push(account.payto_uri);
}
const { isTrusted, isAudited } = await ws.exchangeOps.getExchangeTrust(
ws,
exchange,
);
let hasDenomWithAgeRestriction = false;
logger.trace("computing earliest deposit expiration");
@ -1792,8 +1796,6 @@ export async function getExchangeWithdrawalInfo(
exchangePaytoUris: paytoUris,
exchangeWireAccounts,
exchangeVersion: exchangeDetails.protocolVersionRange || "unknown",
isAudited,
isTrusted,
numOfferedDenoms: possibleDenoms.length,
selectedDenoms,
// FIXME: delete this field / replace by something we can display to the user
@ -2210,8 +2212,6 @@ export interface PrepareCreateWithdrawalGroupResult {
withdrawalGroup: WithdrawalGroupRecord;
transactionId: string;
creationInfo?: {
isTrusted: boolean;
isAudited: boolean;
amount: AmountJson;
canonExchange: string;
exchangeDetails: ExchangeDetailsRecord;
@ -2306,10 +2306,6 @@ export async function internalPrepareCreateWithdrawalGroup(
logger.trace(exchangeDetails);
throw Error("exchange not updated");
}
const { isAudited, isTrusted } = await getExchangeTrust(
ws,
exchangeInfo.exchange,
);
const transactionId = constructTransactionIdentifier({
tag: TransactionType.Withdrawal,
withdrawalGroupId: withdrawalGroup.withdrawalGroupId,
@ -2319,8 +2315,6 @@ export async function internalPrepareCreateWithdrawalGroup(
withdrawalGroup,
transactionId,
creationInfo: {
isAudited,
isTrusted,
canonExchange,
amount,
exchangeDetails,
@ -2339,7 +2333,6 @@ export async function internalPerformCreateWithdrawalGroup(
withdrawalGroups: typeof WalletStoresV1.withdrawalGroups;
reserves: typeof WalletStoresV1.reserves;
exchanges: typeof WalletStoresV1.exchanges;
exchangeTrust: typeof WalletStoresV1.exchangeTrust;
}>,
prep: PrepareCreateWithdrawalGroupResult,
): Promise<PerformCreateWithdrawalGroupResult> {
@ -2347,7 +2340,7 @@ export async function internalPerformCreateWithdrawalGroup(
if (!prep.creationInfo) {
return { withdrawalGroup, transitionInfo: undefined };
}
const { isAudited, isTrusted, amount, canonExchange, exchangeDetails } =
const { amount, canonExchange, exchangeDetails } =
prep.creationInfo;
await tx.withdrawalGroups.add(withdrawalGroup);
@ -2363,15 +2356,6 @@ export async function internalPerformCreateWithdrawalGroup(
await tx.exchanges.put(exchange);
}
if (!isAudited && !isTrusted) {
await tx.exchangeTrust.put({
currency: amount.currency,
exchangeBaseUrl: canonExchange,
exchangeMasterPub: exchangeDetails.masterPublicKey,
uids: [encodeCrock(getRandomBytes(32))],
});
}
const oldTxState = {
major: TransactionMajorState.None,
minor: undefined,
@ -2417,7 +2401,6 @@ export async function internalCreateWithdrawalGroup(
x.reserves,
x.exchanges,
x.exchangeDetails,
x.exchangeTrust,
])
.runReadWrite(async (tx) => {
return await internalPerformCreateWithdrawalGroup(ws, tx, prep);
@ -2563,7 +2546,6 @@ export async function createManualWithdrawal(
x.withdrawalGroups,
x.exchanges,
x.exchangeDetails,
x.exchangeTrust,
])
.runReadOnly(async (tx) => {
return await getFundingPaytoUris(tx, withdrawalGroup.withdrawalGroupId);

View File

@ -121,7 +121,7 @@ import {
DeleteStoredBackupRequest,
TestingSetTimetravelRequest,
} from "@gnu-taler/taler-util";
import { AuditorTrustRecord, WalletContractData } from "./db.js";
import { WalletContractData } from "./db.js";
import {
AddBackupProviderRequest,
AddBackupProviderResponse,
@ -260,7 +260,6 @@ export interface WalletConfig {
*/
builtin: {
exchanges: string[];
auditors: AuditorTrustRecord[];
};
/**

View File

@ -199,7 +199,6 @@ import {
downloadTosFromAcceptedFormat,
getExchangeDetails,
getExchangeRequestTimeout,
getExchangeTrust,
provideExchangeRecordInTx,
updateExchangeFromUrl,
updateExchangeFromUrlHandler,
@ -527,7 +526,7 @@ async function runTaskLoop(
*/
async function fillDefaults(ws: InternalWalletState): Promise<void> {
await ws.db
.mktx((x) => [x.config, x.auditorTrust, x.exchanges, x.exchangeDetails])
.mktx((x) => [x.config, x.exchanges, x.exchangeDetails])
.runReadWrite(async (tx) => {
const appliedRec = await tx.config.get("currencyDefaultsApplied");
let alreadyApplied = appliedRec ? !!appliedRec.value : false;
@ -535,10 +534,6 @@ async function fillDefaults(ws: InternalWalletState): Promise<void> {
logger.trace("defaults already applied");
return;
}
logger.info("importing default exchanges and auditors");
for (const c of ws.config.builtin.auditors) {
await tx.auditorTrust.put(c);
}
for (const baseUrl of ws.config.builtin.exchanges) {
await addPresetExchangeEntry(tx, baseUrl);
const now = AbsoluteTime.now();
@ -1558,24 +1553,11 @@ async function dispatchRequestInternal<Op extends WalletApiOperation>(
return {};
}
case WalletApiOperation.ListCurrencies: {
return await ws.db
.mktx((x) => [x.auditorTrust, x.exchangeTrust])
.runReadOnly(async (tx) => {
const trustedAuditors = await tx.auditorTrust.iter().toArray();
const trustedExchanges = await tx.exchangeTrust.iter().toArray();
return {
trustedAuditors: trustedAuditors.map((x) => ({
currency: x.currency,
auditorBaseUrl: x.auditorBaseUrl,
auditorPub: x.auditorPub,
})),
trustedExchanges: trustedExchanges.map((x) => ({
currency: x.currency,
exchangeBaseUrl: x.exchangeBaseUrl,
exchangeMasterPub: x.exchangeMasterPub,
})),
};
});
// FIXME: Remove / change to scoped currency approach.
return {
trustedAuditors: [],
trustedExchanges: [],
};
}
case WalletApiOperation.WithdrawFakebank: {
const req = codecForWithdrawFakebankRequest().decode(payload);
@ -1780,14 +1762,6 @@ export class Wallet {
public static defaultConfig: Readonly<WalletConfig> = {
builtin: {
exchanges: ["https://exchange.demo.taler.net/"],
auditors: [
{
currency: "KUDOS",
auditorPub: "BW9DC48PHQY4NH011SHHX36DZZ3Q22Y6X7FZ1VD1CMZ2PTFZ6PN0",
auditorBaseUrl: "https://auditor.demo.taler.net/",
uids: ["5P25XF8TVQP9AW6VYGY2KV47WT5Y3ZXFSJAA570GJPX5SVJXKBVG"],
},
],
},
features: {
allowHttp: false,
@ -1860,7 +1834,6 @@ class InternalWalletStateImpl implements InternalWalletState {
exchangeOps: ExchangeOperations = {
getExchangeDetails,
getExchangeTrust,
updateExchangeFromUrl,
};