From 4c9fc48ad5743be677a29e0ea82a59f14f3e42c2 Mon Sep 17 00:00:00 2001 From: tornadocontrib Date: Wed, 25 Sep 2024 08:40:15 +0000 Subject: [PATCH] Tornado CLI 1.0.9-alpha * improve event sync * use latest core deps --- dist/cli.js | 142 ++++++++++++++++------------------ dist/services/nodeEvents.d.ts | 51 ++++++------ package.json | 4 +- src/program.ts | 102 +++++++++--------------- src/services/nodeEvents.ts | 67 +++++++++++----- yarn.lock | 6 +- 6 files changed, 185 insertions(+), 187 deletions(-) diff --git a/dist/cli.js b/dist/cli.js index 8cbabb3..e10d9f8 100644 --- a/dist/cli.js +++ b/dist/cli.js @@ -176375,6 +176375,8 @@ const defaultConfig = { gasLimit: 7e5 } }, + // Inactive tokens to filter from schema verification and syncing events + disabledTokens: ["cdai", "usdt", "usdc"], relayerEnsSubdomain: "mainnet-tornado", pollInterval: 15, constants: { @@ -176832,9 +176834,16 @@ function getConfig(netId) { } return chainConfig; } -function getInstanceByAddress({ netId, address }) { - const { tokens } = getConfig(netId); +function getActiveTokens(config) { + const { tokens, disabledTokens } = config; + return Object.keys(tokens).filter((t) => !(disabledTokens == null ? void 0 : disabledTokens.includes(t))); +} +function getInstanceByAddress(config, address) { + const { tokens, disabledTokens } = config; for (const [currency, { instanceAddress }] of Object.entries(tokens)) { + if (disabledTokens == null ? void 0 : disabledTokens.includes(currency)) { + continue; + } for (const [amount, instance] of Object.entries(instanceAddress)) { if (instance === address) { return { @@ -176845,10 +176854,6 @@ function getInstanceByAddress({ netId, address }) { } } } -function getSubdomains() { - const allConfig = getNetworkConfig(); - return enabledChains.map((chain) => allConfig[chain].relayerEnsSubdomain); -} function getRelayerEnsSubdomains() { const allConfig = getNetworkConfig(); return enabledChains.reduce((acc, chain) => { @@ -176888,7 +176893,7 @@ const statusSchema = { required: ["rewardAccount", "instances", "netId", "tornadoServiceFee", "version", "health"] }; function getStatusSchema(netId, config) { - const { tokens, optionalTokens = [], nativeCurrency } = config; + const { tokens, optionalTokens, disabledTokens, nativeCurrency } = config; const schema = JSON.parse(JSON.stringify(statusSchema)); const instances = Object.keys(tokens).reduce( (acc, token) => { @@ -176919,7 +176924,7 @@ function getStatusSchema(netId, config) { instanceProperties.properties.symbol = { enum: [symbol] }; } acc.properties[token] = instanceProperties; - if (!optionalTokens.includes(token)) { + if (!(optionalTokens == null ? void 0 : optionalTokens.includes(token)) && !(disabledTokens == null ? void 0 : disabledTokens.includes(token))) { acc.required.push(token); } return acc; @@ -177023,18 +177028,6 @@ var __async$9 = (__this, __arguments, generator) => { const MIN_FEE = 0.1; const MAX_FEE = 0.6; const MIN_STAKE_BALANCE = parseEther("500"); -const semVerRegex = new RegExp("^(?0|[1-9]\\d*)\\.(?0|[1-9]\\d*)\\.(?0|[1-9]\\d*)(?:-(?(?:0|[1-9]\\d*|\\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\\.(?:0|[1-9]\\d*|\\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\\+(?[0-9a-zA-Z-]+(?:\\.[0-9a-zA-Z-]+)*))?$"); -function parseSemanticVersion(version) { - const { groups } = semVerRegex.exec(version); - return groups; -} -function isRelayerUpdated(relayerVersion, netId) { - const { major, patch, prerelease } = parseSemanticVersion(relayerVersion); - const requiredMajor = netId === NetId.MAINNET ? "4" : "5"; - const isUpdatedMajor = major === requiredMajor; - if (prerelease) return false; - return isUpdatedMajor && (Number(patch) >= 5 || netId !== NetId.MAINNET); -} function calculateScore({ stakeBalance, tornadoServiceFee }) { if (tornadoServiceFee < MIN_FEE) { tornadoServiceFee = MIN_FEE; @@ -177106,9 +177099,6 @@ class RelayerClient { if (relayerAddress && this.netId === NetId.MAINNET && status.rewardAccount !== relayerAddress) { throw new Error("The Relayer reward address must match registered address"); } - if (!isRelayerUpdated(status.version, this.netId)) { - throw new Error("Outdated version."); - } return status; }); } @@ -181125,7 +181115,7 @@ function calculateSnarkProof(input, circuit, provingKey) { ;// CONCATENATED MODULE: ./package.json -const package_namespaceObject = /*#__PURE__*/JSON.parse('{"rE":"1.0.8-alpha","h_":"Modern Toolsets for Privacy Pools on Ethereum"}'); +const package_namespaceObject = /*#__PURE__*/JSON.parse('{"rE":"1.0.9-alpha","h_":"Modern Toolsets for Privacy Pools on Ethereum"}'); var package_namespaceObject_0 = /*#__PURE__*/__webpack_require__.t(package_namespaceObject, 2); ;// CONCATENATED MODULE: external "module" const external_module_namespaceObject = require("module"); @@ -184033,7 +184023,10 @@ class NodeTornadoService extends BaseTornadoService { deployedBlock, fetchDataOptions, cacheDirectory, - userDirectory + userDirectory, + nativeCurrency, + merkleTreeService, + treeCache }) { super({ netId, @@ -184049,6 +184042,9 @@ class NodeTornadoService extends BaseTornadoService { }); this.cacheDirectory = cacheDirectory; this.userDirectory = userDirectory; + this.nativeCurrency = nativeCurrency; + this.merkleTreeService = merkleTreeService; + this.treeCache = treeCache; } updateEventProgress({ type, fromBlock, toBlock, count }) { if (toBlock) { @@ -184160,6 +184156,14 @@ class NodeTornadoService extends BaseTornadoService { ); console.log(eventTable.toString() + "\n"); if (this.userDirectory) { + if (this.merkleTreeService) { + const tree = yield this.merkleTreeService.verifyTree(events); + if (this.currency === this.nativeCurrency && this.treeCache) { + yield this.treeCache.createTree(events, tree); + console.log(`${this.getInstanceName()}: Updated tree cache with root ${toFixedHex(BigInt(tree.root))} +`); + } + } yield saveUserFile({ fileName: instanceName + ".json", userDirectory: this.userDirectory, @@ -185038,12 +185042,11 @@ var program_async = (__this, __arguments, generator) => { const EXEC_NAME = "tornado-cli"; -const INACTIVE_TOKENS = ["cdai", "usdc", "usdt"]; const DEFAULT_GAS_LIMIT = Number((external_process_default()).env.DEFAULT_GAS_LIMIT) || 6e5; const RELAYER_NETWORK = Number((external_process_default()).env.RELAYER_NETWORK) || NetId.MAINNET; const STATIC_DIR = (external_process_default()).env.CACHE_DIR || external_path_default().join(__dirname, "../static"); const EVENTS_DIR = external_path_default().join(STATIC_DIR, "./events"); -const MERKLE_WORKER_PATH = (external_process_default()).env.DISABLE_MERKLE_WORKER === "true" ? void 0 : external_path_default().join(STATIC_DIR, "./merkleTreeWorker.js"); +const merkleWorkerPath = external_path_default().join(STATIC_DIR, "./merkleTreeWorker.js"); const USER_DIR = (external_process_default()).env.USER_DIR || "."; const SAVED_DIR = external_path_default().join(USER_DIR, "./events"); const SAVED_TREE_DIR = external_path_default().join(USER_DIR, "./trees"); @@ -185185,7 +185188,6 @@ function getProgramRelayer(_0) { }, ethConfig ); - const relayerEnsSubdomains = getRelayerEnsSubdomains(); const registryService = new NodeRegistryService({ netId: RELAYER_NETWORK, provider, @@ -185193,7 +185195,7 @@ function getProgramRelayer(_0) { subgraphName: registrySubgraph, RelayerRegistry: RelayerRegistry__factory.connect(registryContract, provider), Aggregator: Aggregator__factory.connect(aggregatorContract, provider), - relayerEnsSubdomains, + relayerEnsSubdomains: getRelayerEnsSubdomains(), deployedBlock: REGISTRY_BLOCK, fetchDataOptions: fetchDataOptions2, cacheDirectory: EVENTS_DIR, @@ -185595,7 +185597,8 @@ function tornadoProgram() { deployedBlock, fetchDataOptions: fetchDataOptions2, cacheDirectory: EVENTS_DIR, - userDirectory: SAVED_DIR + userDirectory: SAVED_DIR, + nativeCurrency }; const depositsService = new NodeTornadoService(program_spreadProps(program_spreadValues({}, TornadoServiceConstructor), { type: "Deposit" @@ -185608,10 +185611,10 @@ function tornadoProgram() { amount, currency, Tornado, - merkleWorkerPath: MERKLE_WORKER_PATH + merkleWorkerPath }); const depositEvents = (yield depositsService.updateEvents()).events; - const depositTreePromise = MERKLE_WORKER_PATH ? merkleTreeService.verifyTree(depositEvents) : yield merkleTreeService.verifyTree(depositEvents); + const depositTreePromise = merkleTreeService.verifyTree(depositEvents); const withdrawalEvents = (yield withdrawalsService.updateEvents()).events; const depositEvent = depositEvents.find(({ commitment }) => commitment === commitmentHex); const withdrawalEvent = withdrawalEvents.find(({ nullifierHash }) => nullifierHash === nullifierHex); @@ -185808,6 +185811,7 @@ function tornadoProgram() { const { tornadoSubgraph, deployedBlock, + nativeCurrency, tokens: { [currency]: currencyConfig } } = config; const { @@ -185830,27 +185834,24 @@ function tornadoProgram() { deployedBlock, fetchDataOptions: fetchDataOptions2, cacheDirectory: EVENTS_DIR, - userDirectory: SAVED_DIR + userDirectory: SAVED_DIR, + nativeCurrency }; const depositsService = new NodeTornadoService(program_spreadProps(program_spreadValues({}, TornadoServiceConstructor), { - type: "Deposit" + type: "Deposit", + merkleTreeService: new MerkleTreeService({ + netId, + amount, + currency, + Tornado, + merkleWorkerPath + }) })); const withdrawalsService = new NodeTornadoService(program_spreadProps(program_spreadValues({}, TornadoServiceConstructor), { type: "Withdrawal" })); - const merkleTreeService = new MerkleTreeService({ - netId, - amount, - currency, - Tornado, - merkleWorkerPath: MERKLE_WORKER_PATH - }); const depositEvents = (yield depositsService.updateEvents()).events; - const depositTreePromise = MERKLE_WORKER_PATH ? merkleTreeService.verifyTree(depositEvents) : yield merkleTreeService.verifyTree(depositEvents); - const [withdrawalEvents] = yield Promise.all([ - withdrawalsService.updateEvents().then(({ events }) => events), - depositTreePromise - ]); + const withdrawalEvents = (yield withdrawalsService.updateEvents()).events; const depositEvent = depositEvents.find(({ commitment }) => commitment === commitmentHex); const withdrawalEvent = withdrawalEvents.find(({ nullifierHash }) => nullifierHash === nullifierHex); const complianceTable = new (cli_table3_default())(); @@ -185930,7 +185931,6 @@ function tornadoProgram() { yield governanceService.updateEvents(); } if (registryContract && aggregatorContract) { - const relayerEnsSubdomains = getRelayerEnsSubdomains(); const registryService = new NodeRegistryService({ netId, provider, @@ -185938,7 +185938,7 @@ function tornadoProgram() { subgraphName: registrySubgraph, RelayerRegistry: RelayerRegistry__factory.connect(registryContract, provider), Aggregator: Aggregator__factory.connect(aggregatorContract, provider), - relayerEnsSubdomains, + relayerEnsSubdomains: getRelayerEnsSubdomains(), deployedBlock: REGISTRY_BLOCK, fetchDataOptions: fetchDataOptions2, cacheDirectory: EVENTS_DIR, @@ -185970,11 +185970,8 @@ function tornadoProgram() { userDirectory: SAVED_DIR }); yield encryptedNotesService.updateEvents(); - const currencies = currencyOpts ? [currencyOpts.toLowerCase()] : Object.keys(tokens); + const currencies = currencyOpts ? [currencyOpts.toLowerCase()] : getActiveTokens(config); for (const currency of currencies) { - if (INACTIVE_TOKENS.includes(currency)) { - continue; - } const currencyConfig = tokens[currency]; const amounts = Object.keys(currencyConfig.instanceAddress); for (const amount of amounts) { @@ -185991,33 +185988,30 @@ function tornadoProgram() { deployedBlock, fetchDataOptions: fetchDataOptions2, cacheDirectory: EVENTS_DIR, - userDirectory: SAVED_DIR + userDirectory: SAVED_DIR, + nativeCurrency }; const depositsService = new NodeTornadoService(program_spreadProps(program_spreadValues({}, TornadoServiceConstructor), { - type: "Deposit" + type: "Deposit", + merkleTreeService: new MerkleTreeService({ + netId, + amount, + currency, + Tornado, + merkleWorkerPath + }), + treeCache: new TreeCache({ + netId, + amount, + currency, + userDirectory: SAVED_TREE_DIR + }) })); const withdrawalsService = new NodeTornadoService(program_spreadProps(program_spreadValues({}, TornadoServiceConstructor), { type: "Withdrawal" })); - const merkleTreeService = new MerkleTreeService({ - netId, - amount, - currency, - Tornado, - merkleWorkerPath: MERKLE_WORKER_PATH - }); - const treeCache = new TreeCache({ - netId, - amount, - currency, - userDirectory: SAVED_TREE_DIR - }); - const depositEvents = (yield depositsService.updateEvents()).events; - const depositTreePromise = MERKLE_WORKER_PATH ? merkleTreeService.verifyTree(depositEvents) : yield merkleTreeService.verifyTree(depositEvents); - const [tree] = yield Promise.all([depositTreePromise, withdrawalsService.updateEvents()]); - if (nativeCurrency === currency) { - yield treeCache.createTree(depositEvents, tree); - } + yield depositsService.updateEvents(); + yield withdrawalsService.updateEvents(); } } } @@ -186203,7 +186197,7 @@ function tornadoProgram() { [{ colSpan: 2, content: `Account key: ${accountKey}`, hAlign: "center" }], ["blockNumber", "note"].map((content) => ({ content: lib_default().red.bold(content) })), ...noteAccount.decryptNotes(encryptedNoteEvents).map(({ blockNumber, address, noteHex }) => { - const { amount, currency } = getInstanceByAddress({ netId, address }); + const { amount, currency } = getInstanceByAddress(config, address) || {}; return [blockNumber, `tornado-${currency}-${amount}-${netId}-${noteHex}`]; }) ); diff --git a/dist/services/nodeEvents.d.ts b/dist/services/nodeEvents.d.ts index d925607..d94fe52 100644 --- a/dist/services/nodeEvents.d.ts +++ b/dist/services/nodeEvents.d.ts @@ -1,13 +1,20 @@ import { BatchBlockOnProgress, BatchEventOnProgress, BaseTornadoService, BaseEncryptedNotesService, BaseGovernanceService, BaseRegistryService, BaseTornadoServiceConstructor, BaseEncryptedNotesServiceConstructor, BaseGovernanceServiceConstructor, BaseRegistryServiceConstructor, BaseEchoServiceConstructor, BaseEchoService, CachedRelayers } from '@tornado/core'; -import type { BaseEvents, DepositsEvents, WithdrawalsEvents, EncryptedNotesEvents, RegistersEvents, AllGovernanceEvents, EchoEvents } from '@tornado/core'; +import type { BaseEvents, DepositsEvents, WithdrawalsEvents, EncryptedNotesEvents, RegistersEvents, AllGovernanceEvents, EchoEvents, MerkleTreeService } from '@tornado/core'; +import { TreeCache } from './treeCache'; export type NodeTornadoServiceConstructor = BaseTornadoServiceConstructor & { - cacheDirectory?: string; - userDirectory?: string; + cacheDirectory: string; + userDirectory: string; + nativeCurrency: string; + merkleTreeService?: MerkleTreeService; + treeCache?: TreeCache; }; export declare class NodeTornadoService extends BaseTornadoService { - cacheDirectory?: string; - userDirectory?: string; - constructor({ netId, provider, graphApi, subgraphName, Tornado, type, amount, currency, deployedBlock, fetchDataOptions, cacheDirectory, userDirectory, }: NodeTornadoServiceConstructor); + cacheDirectory: string; + userDirectory: string; + nativeCurrency: string; + merkleTreeService?: MerkleTreeService; + treeCache?: TreeCache; + constructor({ netId, provider, graphApi, subgraphName, Tornado, type, amount, currency, deployedBlock, fetchDataOptions, cacheDirectory, userDirectory, nativeCurrency, merkleTreeService, treeCache, }: NodeTornadoServiceConstructor); updateEventProgress({ type, fromBlock, toBlock, count }: Parameters[0]): void; updateTransactionProgress({ currentIndex, totalIndex }: Parameters[0]): void; updateBlockProgress({ currentIndex, totalIndex }: Parameters[0]): void; @@ -17,12 +24,12 @@ export declare class NodeTornadoService extends BaseTornadoService { saveEvents({ events, lastBlock }: BaseEvents): Promise; } export type NodeEchoServiceConstructor = BaseEchoServiceConstructor & { - cacheDirectory?: string; - userDirectory?: string; + cacheDirectory: string; + userDirectory: string; }; export declare class NodeEchoService extends BaseEchoService { - cacheDirectory?: string; - userDirectory?: string; + cacheDirectory: string; + userDirectory: string; constructor({ netId, provider, graphApi, subgraphName, Echoer, deployedBlock, fetchDataOptions, cacheDirectory, userDirectory, }: NodeEchoServiceConstructor); updateEventProgress({ type, fromBlock, toBlock, count }: Parameters[0]): void; updateGraphProgress({ type, fromBlock, toBlock, count }: Parameters[0]): void; @@ -31,12 +38,12 @@ export declare class NodeEchoService extends BaseEchoService { saveEvents({ events, lastBlock }: BaseEvents): Promise; } export type NodeEncryptedNotesServiceConstructor = BaseEncryptedNotesServiceConstructor & { - cacheDirectory?: string; - userDirectory?: string; + cacheDirectory: string; + userDirectory: string; }; export declare class NodeEncryptedNotesService extends BaseEncryptedNotesService { - cacheDirectory?: string; - userDirectory?: string; + cacheDirectory: string; + userDirectory: string; constructor({ netId, provider, graphApi, subgraphName, Router, deployedBlock, fetchDataOptions, cacheDirectory, userDirectory, }: NodeEncryptedNotesServiceConstructor); updateEventProgress({ type, fromBlock, toBlock, count }: Parameters[0]): void; updateGraphProgress({ type, fromBlock, toBlock, count }: Parameters[0]): void; @@ -45,12 +52,12 @@ export declare class NodeEncryptedNotesService extends BaseEncryptedNotesService saveEvents({ events, lastBlock }: BaseEvents): Promise; } export type NodeGovernanceServiceConstructor = BaseGovernanceServiceConstructor & { - cacheDirectory?: string; - userDirectory?: string; + cacheDirectory: string; + userDirectory: string; }; export declare class NodeGovernanceService extends BaseGovernanceService { - cacheDirectory?: string; - userDirectory?: string; + cacheDirectory: string; + userDirectory: string; constructor({ netId, provider, graphApi, subgraphName, Governance, deployedBlock, fetchDataOptions, cacheDirectory, userDirectory, }: NodeGovernanceServiceConstructor); updateEventProgress({ type, fromBlock, toBlock, count }: Parameters[0]): void; updateGraphProgress({ type, fromBlock, toBlock, count }: Parameters[0]): void; @@ -60,12 +67,12 @@ export declare class NodeGovernanceService extends BaseGovernanceService { saveEvents({ events, lastBlock }: BaseEvents): Promise; } export type NodeRegistryServiceConstructor = BaseRegistryServiceConstructor & { - cacheDirectory?: string; - userDirectory?: string; + cacheDirectory: string; + userDirectory: string; }; export declare class NodeRegistryService extends BaseRegistryService { - cacheDirectory?: string; - userDirectory?: string; + cacheDirectory: string; + userDirectory: string; constructor({ netId, provider, graphApi, subgraphName, RelayerRegistry, Aggregator, relayerEnsSubdomains, deployedBlock, fetchDataOptions, cacheDirectory, userDirectory, }: NodeRegistryServiceConstructor); updateEventProgress({ type, fromBlock, toBlock, count }: Parameters[0]): void; updateGraphProgress({ type, fromBlock, toBlock, count }: Parameters[0]): void; diff --git a/package.json b/package.json index 3461824..a9ec96e 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@tornado/cli", - "version": "1.0.8-alpha", + "version": "1.0.9-alpha", "description": "Modern Toolsets for Privacy Pools on Ethereum", "main": "./dist/cli.js", "types": "./dist/cli.d.ts", @@ -51,7 +51,7 @@ "optionalDependencies": {}, "devDependencies": { "@colors/colors": "1.5.0", - "@tornado/core": "git+https://git.tornado.ws/tornadocontrib/tornado-core.git#d0b032d7bef06de61872ba7ad07b769b9b1d9717", + "@tornado/core": "git+https://git.tornado.ws/tornadocontrib/tornado-core.git#f7fdf7db0a813ae2193f9864e212d68dc840c0d7", "@typechain/ethers-v6": "^0.5.1", "@types/figlet": "^1.5.8", "@typescript-eslint/eslint-plugin": "^8.6.0", diff --git a/src/program.ts b/src/program.ts index f6b7bd9..223134f 100644 --- a/src/program.ts +++ b/src/program.ts @@ -67,6 +67,7 @@ import { getSupportedInstances, initGroth16, getRelayerEnsSubdomains, + getActiveTokens, } from '@tornado/core'; import * as packageJson from '../package.json'; import { @@ -87,9 +88,6 @@ import { const EXEC_NAME = 'tornado-cli'; -// Inactive tokens to filter from syncing (Either they have no activity for more than a year, should be filtered from event syncs and withdrawals) -const INACTIVE_TOKENS: string[] = ['cdai', 'usdc', 'usdt']; - /** * Static variables, shouldn't be modified by env unless you know what they are doing */ @@ -100,8 +98,7 @@ const RELAYER_NETWORK = Number(process.env.RELAYER_NETWORK) || NetId.MAINNET; // Where cached events, trees, circuits, and key is saved const STATIC_DIR = process.env.CACHE_DIR || path.join(__dirname, '../static'); const EVENTS_DIR = path.join(STATIC_DIR, './events'); -const MERKLE_WORKER_PATH = - process.env.DISABLE_MERKLE_WORKER === 'true' ? undefined : path.join(STATIC_DIR, './merkleTreeWorker.js'); +const merkleWorkerPath = path.join(STATIC_DIR, './merkleTreeWorker.js'); // Where we should backup notes and save events const USER_DIR = process.env.USER_DIR || '.'; @@ -315,8 +312,6 @@ export async function getProgramRelayer({ ethConfig, ); - const relayerEnsSubdomains = getRelayerEnsSubdomains(); - const registryService = new NodeRegistryService({ netId: RELAYER_NETWORK, provider, @@ -324,7 +319,7 @@ export async function getProgramRelayer({ subgraphName: registrySubgraph, RelayerRegistry: RelayerRegistry__factory.connect(registryContract as string, provider), Aggregator: Aggregator__factory.connect(aggregatorContract as string, provider), - relayerEnsSubdomains, + relayerEnsSubdomains: getRelayerEnsSubdomains(), deployedBlock: REGISTRY_BLOCK, fetchDataOptions, cacheDirectory: EVENTS_DIR, @@ -874,6 +869,7 @@ export function tornadoProgram() { fetchDataOptions, cacheDirectory: EVENTS_DIR, userDirectory: SAVED_DIR, + nativeCurrency, }; const depositsService = new NodeTornadoService({ @@ -891,15 +887,13 @@ export function tornadoProgram() { amount, currency, Tornado, - merkleWorkerPath: MERKLE_WORKER_PATH, + merkleWorkerPath, }); const depositEvents = (await depositsService.updateEvents()).events as DepositsEvents[]; - // If we have MERKLE_WORKER_PATH run worker at background otherwise resolve it here - const depositTreePromise = MERKLE_WORKER_PATH - ? merkleTreeService.verifyTree(depositEvents) - : await merkleTreeService.verifyTree(depositEvents); + // Create tree using node workers which would spawn another dedicated thread to create trees + const depositTreePromise = merkleTreeService.verifyTree(depositEvents); const withdrawalEvents = (await withdrawalsService.updateEvents()).events as WithdrawalsEvents[]; @@ -1166,6 +1160,7 @@ export function tornadoProgram() { const { tornadoSubgraph, deployedBlock, + nativeCurrency, tokens: { [currency]: currencyConfig }, } = config; @@ -1195,11 +1190,19 @@ export function tornadoProgram() { fetchDataOptions, cacheDirectory: EVENTS_DIR, userDirectory: SAVED_DIR, + nativeCurrency, }; const depositsService = new NodeTornadoService({ ...TornadoServiceConstructor, type: 'Deposit', + merkleTreeService: new MerkleTreeService({ + netId, + amount, + currency, + Tornado, + merkleWorkerPath, + }), }); const withdrawalsService = new NodeTornadoService({ @@ -1207,25 +1210,9 @@ export function tornadoProgram() { type: 'Withdrawal', }); - const merkleTreeService = new MerkleTreeService({ - netId, - amount, - currency, - Tornado, - merkleWorkerPath: MERKLE_WORKER_PATH, - }); - const depositEvents = (await depositsService.updateEvents()).events as DepositsEvents[]; - // If we have MERKLE_WORKER_PATH run worker at background otherwise resolve it here - const depositTreePromise = MERKLE_WORKER_PATH - ? merkleTreeService.verifyTree(depositEvents) - : await merkleTreeService.verifyTree(depositEvents); - - const [withdrawalEvents] = await Promise.all([ - withdrawalsService.updateEvents().then(({ events }) => events as WithdrawalsEvents[]), - depositTreePromise, - ]); + const withdrawalEvents = (await withdrawalsService.updateEvents()).events as WithdrawalsEvents[]; const depositEvent = depositEvents.find(({ commitment }) => commitment === commitmentHex); @@ -1327,8 +1314,6 @@ export function tornadoProgram() { } if (registryContract && aggregatorContract) { - const relayerEnsSubdomains = getRelayerEnsSubdomains(); - const registryService = new NodeRegistryService({ netId, provider, @@ -1336,7 +1321,7 @@ export function tornadoProgram() { subgraphName: registrySubgraph, RelayerRegistry: RelayerRegistry__factory.connect(registryContract, provider), Aggregator: Aggregator__factory.connect(aggregatorContract, provider), - relayerEnsSubdomains, + relayerEnsSubdomains: getRelayerEnsSubdomains(), deployedBlock: REGISTRY_BLOCK, fetchDataOptions, cacheDirectory: EVENTS_DIR, @@ -1374,14 +1359,9 @@ export function tornadoProgram() { await encryptedNotesService.updateEvents(); - const currencies = currencyOpts ? [currencyOpts.toLowerCase()] : Object.keys(tokens); + const currencies = currencyOpts ? [currencyOpts.toLowerCase()] : getActiveTokens(config); for (const currency of currencies) { - // Skip syncing inactive instances - if (INACTIVE_TOKENS.includes(currency)) { - continue; - } - const currencyConfig = tokens[currency]; // Now load the denominations and address const amounts = Object.keys(currencyConfig.instanceAddress); @@ -1403,11 +1383,25 @@ export function tornadoProgram() { fetchDataOptions, cacheDirectory: EVENTS_DIR, userDirectory: SAVED_DIR, + nativeCurrency, }; const depositsService = new NodeTornadoService({ ...TornadoServiceConstructor, type: 'Deposit', + merkleTreeService: new MerkleTreeService({ + netId, + amount, + currency, + Tornado, + merkleWorkerPath, + }), + treeCache: new TreeCache({ + netId, + amount, + currency, + userDirectory: SAVED_TREE_DIR, + }), }); const withdrawalsService = new NodeTornadoService({ @@ -1415,33 +1409,9 @@ export function tornadoProgram() { type: 'Withdrawal', }); - const merkleTreeService = new MerkleTreeService({ - netId, - amount, - currency, - Tornado, - merkleWorkerPath: MERKLE_WORKER_PATH, - }); + await depositsService.updateEvents(); - const treeCache = new TreeCache({ - netId, - amount, - currency, - userDirectory: SAVED_TREE_DIR, - }); - - const depositEvents = (await depositsService.updateEvents()).events as DepositsEvents[]; - - // If we have MERKLE_WORKER_PATH run worker at background otherwise resolve it here - const depositTreePromise = MERKLE_WORKER_PATH - ? merkleTreeService.verifyTree(depositEvents) - : await merkleTreeService.verifyTree(depositEvents); - - const [tree] = await Promise.all([depositTreePromise, withdrawalsService.updateEvents()]); - - if (nativeCurrency === currency) { - await treeCache.createTree(depositEvents, tree); - } + await withdrawalsService.updateEvents(); } } } @@ -1696,7 +1666,7 @@ export function tornadoProgram() { [{ colSpan: 2, content: `Account key: ${accountKey}`, hAlign: 'center' }], ['blockNumber', 'note'].map((content) => ({ content: colors.red.bold(content) })), ...noteAccount.decryptNotes(encryptedNoteEvents).map(({ blockNumber, address, noteHex }) => { - const { amount, currency } = getInstanceByAddress({ netId, address }) as { amount: string; currency: string }; + const { amount, currency } = getInstanceByAddress(config, address) || {}; return [blockNumber, `tornado-${currency}-${amount}-${netId}-${noteHex}`]; }), diff --git a/src/services/nodeEvents.ts b/src/services/nodeEvents.ts index 4a6b443..87fa177 100644 --- a/src/services/nodeEvents.ts +++ b/src/services/nodeEvents.ts @@ -17,6 +17,7 @@ import { BaseEchoService, DEPOSIT, CachedRelayers, + toFixedHex, } from '@tornado/core'; import type { BaseEvents, @@ -26,17 +27,26 @@ import type { RegistersEvents, AllGovernanceEvents, EchoEvents, + MerkleTreeService, } from '@tornado/core'; +import { TreeCache } from './treeCache'; import { saveUserFile, loadSavedEvents, loadCachedEvents, saveLegacyFile, existsAsync } from './data'; export type NodeTornadoServiceConstructor = BaseTornadoServiceConstructor & { - cacheDirectory?: string; - userDirectory?: string; + cacheDirectory: string; + userDirectory: string; + nativeCurrency: string; + merkleTreeService?: MerkleTreeService; + treeCache?: TreeCache; }; export class NodeTornadoService extends BaseTornadoService { - cacheDirectory?: string; - userDirectory?: string; + cacheDirectory: string; + userDirectory: string; + nativeCurrency: string; + + merkleTreeService?: MerkleTreeService; + treeCache?: TreeCache; constructor({ netId, @@ -51,6 +61,9 @@ export class NodeTornadoService extends BaseTornadoService { fetchDataOptions, cacheDirectory, userDirectory, + nativeCurrency, + merkleTreeService, + treeCache, }: NodeTornadoServiceConstructor) { super({ netId, @@ -67,6 +80,10 @@ export class NodeTornadoService extends BaseTornadoService { this.cacheDirectory = cacheDirectory; this.userDirectory = userDirectory; + this.nativeCurrency = nativeCurrency; + + this.merkleTreeService = merkleTreeService; + this.treeCache = treeCache; } updateEventProgress({ type, fromBlock, toBlock, count }: Parameters[0]) { @@ -190,6 +207,16 @@ export class NodeTornadoService extends BaseTornadoService { console.log(eventTable.toString() + '\n'); if (this.userDirectory) { + if (this.merkleTreeService) { + const tree = await this.merkleTreeService.verifyTree(events as DepositsEvents[]); + + if (this.currency === this.nativeCurrency && this.treeCache) { + await this.treeCache.createTree(events as DepositsEvents[], tree); + + console.log(`${this.getInstanceName()}: Updated tree cache with root ${toFixedHex(BigInt(tree.root))}\n`); + } + } + await saveUserFile({ fileName: instanceName + '.json', userDirectory: this.userDirectory, @@ -226,13 +253,13 @@ export class NodeTornadoService extends BaseTornadoService { } export type NodeEchoServiceConstructor = BaseEchoServiceConstructor & { - cacheDirectory?: string; - userDirectory?: string; + cacheDirectory: string; + userDirectory: string; }; export class NodeEchoService extends BaseEchoService { - cacheDirectory?: string; - userDirectory?: string; + cacheDirectory: string; + userDirectory: string; constructor({ netId, @@ -372,13 +399,13 @@ export class NodeEchoService extends BaseEchoService { } export type NodeEncryptedNotesServiceConstructor = BaseEncryptedNotesServiceConstructor & { - cacheDirectory?: string; - userDirectory?: string; + cacheDirectory: string; + userDirectory: string; }; export class NodeEncryptedNotesService extends BaseEncryptedNotesService { - cacheDirectory?: string; - userDirectory?: string; + cacheDirectory: string; + userDirectory: string; constructor({ netId, @@ -530,13 +557,13 @@ export class NodeEncryptedNotesService extends BaseEncryptedNotesService { } export type NodeGovernanceServiceConstructor = BaseGovernanceServiceConstructor & { - cacheDirectory?: string; - userDirectory?: string; + cacheDirectory: string; + userDirectory: string; }; export class NodeGovernanceService extends BaseGovernanceService { - cacheDirectory?: string; - userDirectory?: string; + cacheDirectory: string; + userDirectory: string; constructor({ netId, @@ -682,13 +709,13 @@ export class NodeGovernanceService extends BaseGovernanceService { } export type NodeRegistryServiceConstructor = BaseRegistryServiceConstructor & { - cacheDirectory?: string; - userDirectory?: string; + cacheDirectory: string; + userDirectory: string; }; export class NodeRegistryService extends BaseRegistryService { - cacheDirectory?: string; - userDirectory?: string; + cacheDirectory: string; + userDirectory: string; constructor({ netId, diff --git a/yarn.lock b/yarn.lock index 8b8601a..2660d0d 100644 --- a/yarn.lock +++ b/yarn.lock @@ -781,9 +781,9 @@ "@openzeppelin/contracts-v3" "npm:@openzeppelin/contracts@3.2.0-rc.0" ethers "^6.4.0" -"@tornado/core@git+https://git.tornado.ws/tornadocontrib/tornado-core.git#d0b032d7bef06de61872ba7ad07b769b9b1d9717": - version "1.0.13" - resolved "git+https://git.tornado.ws/tornadocontrib/tornado-core.git#d0b032d7bef06de61872ba7ad07b769b9b1d9717" +"@tornado/core@git+https://git.tornado.ws/tornadocontrib/tornado-core.git#f7fdf7db0a813ae2193f9864e212d68dc840c0d7": + version "1.0.14" + resolved "git+https://git.tornado.ws/tornadocontrib/tornado-core.git#f7fdf7db0a813ae2193f9864e212d68dc840c0d7" dependencies: "@metamask/eth-sig-util" "^7.0.3" "@tornado/contracts" "^1.0.1"