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; 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? * Did the user already accept the current terms of service for the exchange?
*/ */
termsOfServiceAccepted: boolean; termsOfServiceAccepted: boolean;
/**
* The exchange is trusted directly.
*/
isTrusted: boolean;
/** /**
* The earliest deposit expiration of the selected coins. * 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; export const WALLET_DB_MINOR_VERSION = 10;
/** /**
* Format of the operation status code: xyznnn * Format of the operation status code: xyznnn
* *
@ -293,61 +291,6 @@ export interface ReserveBankInfo {
timestampBankConfirmed: TalerPreciseTimestamp | undefined; 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. * Status of a denomination.
*/ */
@ -2451,30 +2394,6 @@ export const WalletStoresV1 = {
describeContents<ConfigRecord>({ keyPath: "key" }), 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: describeStore(
"denominations", "denominations",
describeContents<DenominationRecord>({ describeContents<DenominationRecord>({

View File

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

View File

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

View File

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

View File

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

View File

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