wallet-core: fix default auditor/exchange loading logic
This commit is contained in:
parent
99ace8b7d2
commit
957f9a5efb
@ -255,9 +255,9 @@ async function withWallet<T>(
|
||||
console.error("Error details:", JSON.stringify(ed, undefined, 2));
|
||||
process.exit(1);
|
||||
} finally {
|
||||
logger.info("operation with wallet finished, stopping");
|
||||
logger.trace("operation with wallet finished, stopping");
|
||||
wallet.stop();
|
||||
logger.info("stopped wallet");
|
||||
logger.trace("stopped wallet");
|
||||
}
|
||||
}
|
||||
|
||||
@ -495,6 +495,7 @@ walletCli
|
||||
talerWithdrawUri: uri,
|
||||
},
|
||||
);
|
||||
console.log("accept withdrawal response", res);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
@ -731,7 +732,7 @@ const advancedCli = walletCli.subcommand("advancedArgs", "advanced", {
|
||||
|
||||
advancedCli
|
||||
.subcommand("init", "init", {
|
||||
help: "Initialize the wallet (with DB) and exit."
|
||||
help: "Initialize the wallet (with DB) and exit.",
|
||||
})
|
||||
.action(async (args) => {
|
||||
await withWallet(args, async () => {});
|
||||
|
@ -37,7 +37,6 @@ export async function processRequestWithImpl(
|
||||
reqMsg: CryptoWorkerRequestMessage,
|
||||
impl: TalerCryptoInterfaceR,
|
||||
): Promise<CryptoWorkerResponseMessage> {
|
||||
logger.info(`processing crypto request ${j2s(reqMsg)}`);
|
||||
if (typeof reqMsg !== "object") {
|
||||
logger.error("request must be an object");
|
||||
return {
|
||||
|
@ -510,7 +510,7 @@ export interface ExchangeRecord {
|
||||
permanent: boolean;
|
||||
|
||||
/**
|
||||
* Last time when the exchange was updated.
|
||||
* Last time when the exchange was updated (both /keys and /wire).
|
||||
*/
|
||||
lastUpdate: TalerProtocolTimestamp | undefined;
|
||||
|
||||
@ -521,6 +521,10 @@ export interface ExchangeRecord {
|
||||
*/
|
||||
nextUpdate: TalerProtocolTimestamp;
|
||||
|
||||
lastKeysEtag: string | undefined;
|
||||
|
||||
lastWireEtag: string | undefined;
|
||||
|
||||
/**
|
||||
* Next time that we should check if coins need to be refreshed.
|
||||
*
|
||||
|
@ -362,6 +362,8 @@ export async function importBackup(
|
||||
lastUpdate: undefined,
|
||||
nextUpdate: TalerProtocolTimestamp.now(),
|
||||
nextRefreshCheck: TalerProtocolTimestamp.now(),
|
||||
lastKeysEtag: undefined,
|
||||
lastWireEtag: undefined,
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -63,7 +63,11 @@ import {
|
||||
readSuccessResponseJsonOrThrow,
|
||||
readSuccessResponseTextOrThrow,
|
||||
} from "../util/http.js";
|
||||
import { DbAccess, GetReadOnlyAccess } from "../util/query.js";
|
||||
import {
|
||||
DbAccess,
|
||||
GetReadOnlyAccess,
|
||||
GetReadWriteAccess,
|
||||
} from "../util/query.js";
|
||||
import {
|
||||
OperationAttemptResult,
|
||||
OperationAttemptResultType,
|
||||
@ -316,33 +320,35 @@ async function downloadExchangeWireInfo(
|
||||
return wireInfo;
|
||||
}
|
||||
|
||||
async function provideExchangeRecord(
|
||||
export async function provideExchangeRecordInTx(
|
||||
ws: InternalWalletState,
|
||||
tx: GetReadWriteAccess<{
|
||||
exchanges: typeof WalletStoresV1.exchanges;
|
||||
exchangeDetails: typeof WalletStoresV1.exchangeDetails;
|
||||
}>,
|
||||
baseUrl: string,
|
||||
now: AbsoluteTime,
|
||||
): Promise<{
|
||||
exchange: ExchangeRecord;
|
||||
exchangeDetails: ExchangeDetailsRecord | undefined;
|
||||
}> {
|
||||
return await ws.db
|
||||
.mktx((x) => [x.exchanges, x.exchangeDetails])
|
||||
.runReadWrite(async (tx) => {
|
||||
let exchange = await tx.exchanges.get(baseUrl);
|
||||
if (!exchange) {
|
||||
const r: ExchangeRecord = {
|
||||
permanent: true,
|
||||
baseUrl: baseUrl,
|
||||
detailsPointer: undefined,
|
||||
lastUpdate: undefined,
|
||||
nextUpdate: AbsoluteTime.toTimestamp(now),
|
||||
nextRefreshCheck: AbsoluteTime.toTimestamp(now),
|
||||
};
|
||||
await tx.exchanges.put(r);
|
||||
exchange = r;
|
||||
}
|
||||
const exchangeDetails = await getExchangeDetails(tx, baseUrl);
|
||||
return { exchange, exchangeDetails };
|
||||
});
|
||||
let exchange = await tx.exchanges.get(baseUrl);
|
||||
if (!exchange) {
|
||||
const r: ExchangeRecord = {
|
||||
permanent: true,
|
||||
baseUrl: baseUrl,
|
||||
detailsPointer: undefined,
|
||||
lastUpdate: undefined,
|
||||
nextUpdate: AbsoluteTime.toTimestamp(now),
|
||||
nextRefreshCheck: AbsoluteTime.toTimestamp(now),
|
||||
lastKeysEtag: undefined,
|
||||
lastWireEtag: undefined,
|
||||
};
|
||||
await tx.exchanges.put(r);
|
||||
exchange = r;
|
||||
}
|
||||
const exchangeDetails = await getExchangeDetails(tx, baseUrl);
|
||||
return { exchange, exchangeDetails };
|
||||
}
|
||||
|
||||
interface ExchangeKeysDownloadResult {
|
||||
@ -499,15 +505,16 @@ export async function updateExchangeFromUrlHandler(
|
||||
> {
|
||||
const forceNow = options.forceNow ?? false;
|
||||
logger.info(`updating exchange info for ${baseUrl}, forced: ${forceNow}`);
|
||||
console.trace("here");
|
||||
|
||||
const now = AbsoluteTime.now();
|
||||
baseUrl = canonicalizeBaseUrl(baseUrl);
|
||||
|
||||
const { exchange, exchangeDetails } = await provideExchangeRecord(
|
||||
ws,
|
||||
baseUrl,
|
||||
now,
|
||||
);
|
||||
const { exchange, exchangeDetails } = await ws.db
|
||||
.mktx((x) => [x.exchanges, x.exchangeDetails])
|
||||
.runReadWrite(async (tx) => {
|
||||
return provideExchangeRecordInTx(ws, tx, baseUrl, now);
|
||||
});
|
||||
|
||||
if (
|
||||
!forceNow &&
|
||||
|
@ -50,6 +50,7 @@ async function gatherExchangePending(
|
||||
now: AbsoluteTime,
|
||||
resp: PendingOperationsResponse,
|
||||
): Promise<void> {
|
||||
// FIXME: We should do a range query here based on the update time.
|
||||
await tx.exchanges.iter().forEachAsync(async (exch) => {
|
||||
const opTag = RetryTags.forExchangeUpdate(exch);
|
||||
let opr = await tx.operationRetries.get(opTag);
|
||||
|
@ -1071,7 +1071,7 @@ export async function processWithdrawalGroup(
|
||||
case WithdrawalGroupStatus.QueryingStatus: {
|
||||
const doQueryAsync = async () => {
|
||||
if (ws.stopped) {
|
||||
logger.info("not long-polling reserve, wallet already stopped");
|
||||
logger.trace("not long-polling reserve, wallet already stopped");
|
||||
await storeOperationPending(ws, retryTag);
|
||||
return;
|
||||
}
|
||||
@ -1080,7 +1080,7 @@ export async function processWithdrawalGroup(
|
||||
try {
|
||||
ws.activeLongpoll[retryTag] = {
|
||||
cancel: () => {
|
||||
logger.info("cancel of reserve longpoll requested");
|
||||
logger.trace("cancel of reserve longpoll requested");
|
||||
cts.cancel();
|
||||
},
|
||||
};
|
||||
@ -1094,16 +1094,13 @@ export async function processWithdrawalGroup(
|
||||
return;
|
||||
}
|
||||
delete ws.activeLongpoll[retryTag];
|
||||
logger.info(
|
||||
`active longpoll keys (2) ${Object.keys(ws.activeLongpoll)}`,
|
||||
);
|
||||
if (!res.ready) {
|
||||
await storeOperationPending(ws, retryTag);
|
||||
}
|
||||
ws.latch.trigger();
|
||||
};
|
||||
doQueryAsync();
|
||||
logger.info(
|
||||
logger.trace(
|
||||
"returning early from withdrawal for long-polling in background",
|
||||
);
|
||||
return {
|
||||
@ -1918,12 +1915,12 @@ export async function acceptWithdrawalFromUri(
|
||||
);
|
||||
}
|
||||
|
||||
// Start withdrawal in the background.
|
||||
await processWithdrawalGroup(ws, withdrawalGroupId, { forceNow: true }).catch(
|
||||
(err) => {
|
||||
logger.error("Processing withdrawal (after creation) failed:", err);
|
||||
},
|
||||
);
|
||||
// Start withdrawal in the background
|
||||
processWithdrawalGroup(ws, withdrawalGroupId, {
|
||||
forceNow: true,
|
||||
}).catch((err) => {
|
||||
logger.error("Processing withdrawal (after creation) failed:", err);
|
||||
});
|
||||
|
||||
return {
|
||||
reservePub: withdrawalGroup.reservePub,
|
||||
|
@ -155,6 +155,7 @@ import {
|
||||
getExchangeDetails,
|
||||
getExchangeRequestTimeout,
|
||||
getExchangeTrust,
|
||||
provideExchangeRecordInTx,
|
||||
updateExchangeFromUrl,
|
||||
updateExchangeFromUrlHandler,
|
||||
updateExchangeTermsOfService,
|
||||
@ -583,32 +584,26 @@ async function runTaskLoop(
|
||||
*/
|
||||
async function fillDefaults(ws: InternalWalletState): Promise<void> {
|
||||
await ws.db
|
||||
.mktx((x) => [x.config, x.auditorTrust])
|
||||
.mktx((x) => [x.config, x.auditorTrust, x.exchanges, x.exchangeDetails])
|
||||
.runReadWrite(async (tx) => {
|
||||
let applied = false;
|
||||
await tx.config.iter().forEach((x) => {
|
||||
if (x.key == "currencyDefaultsApplied" && x.value == true) {
|
||||
applied = true;
|
||||
}
|
||||
});
|
||||
if (!applied) {
|
||||
for (const c of builtinAuditors) {
|
||||
await tx.auditorTrust.put(c);
|
||||
}
|
||||
const appliedRec = await tx.config.get("currencyDefaultsApplied");
|
||||
let alreadyApplied = appliedRec ? !!appliedRec.value : false;
|
||||
if (alreadyApplied) {
|
||||
logger.info("defaults already applied");
|
||||
return;
|
||||
}
|
||||
// FIXME: make sure exchanges are added transactionally to
|
||||
// DB in first-time default application
|
||||
for (const c of builtinAuditors) {
|
||||
await tx.auditorTrust.put(c);
|
||||
}
|
||||
for (const baseUrl of builtinExchanges) {
|
||||
const now = AbsoluteTime.now();
|
||||
provideExchangeRecordInTx(ws, tx, baseUrl, now);
|
||||
}
|
||||
await tx.config.put({
|
||||
key: "currencyDefaultsApplied",
|
||||
value: true,
|
||||
});
|
||||
});
|
||||
|
||||
for (const url of builtinExchanges) {
|
||||
try {
|
||||
await updateExchangeFromUrl(ws, url, { forceNow: true });
|
||||
} catch (e) {
|
||||
logger.warn(
|
||||
`could not update builtin exchange ${url} during wallet initialization`,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async function getExchangeTos(
|
||||
@ -1719,12 +1714,12 @@ class InternalWalletStateImpl implements InternalWalletState {
|
||||
* Stop ongoing processing.
|
||||
*/
|
||||
stop(): void {
|
||||
logger.info("stopping (at internal wallet state)");
|
||||
logger.trace("stopping (at internal wallet state)");
|
||||
this.stopped = true;
|
||||
this.timerGroup.stopCurrentAndFutureTimers();
|
||||
this.cryptoDispatcher.stop();
|
||||
for (const key of Object.keys(this.activeLongpoll)) {
|
||||
logger.info(`cancelling active longpoll ${key}`);
|
||||
logger.trace(`cancelling active longpoll ${key}`);
|
||||
this.activeLongpoll[key].cancel();
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user