Add NodeMultiTornadoService
This commit is contained in:
parent
d95635c4f8
commit
0b5adaa9c3
2
lib/config.js
vendored
2
lib/config.js
vendored
@ -70,6 +70,6 @@ function getRelayerConfig() {
|
||||
cacheDir: path_1.default.join(STATIC_DIR, './events'),
|
||||
userEventsDir: path_1.default.join(USER_DIR, './events'),
|
||||
userTreeDir: path_1.default.join(USER_DIR, './trees'),
|
||||
syncInterval: Number(process_1.default.env.SYNC_INTERVAL || 120),
|
||||
syncInterval: Number(process_1.default.env.SYNC_INTERVAL || 180),
|
||||
};
|
||||
}
|
||||
|
59
lib/services/events.d.ts
vendored
59
lib/services/events.d.ts
vendored
@ -1,4 +1,4 @@
|
||||
import { BaseTornadoService, BaseEncryptedNotesService, BaseGovernanceService, BaseRegistryService, BaseTornadoServiceConstructor, BaseEncryptedNotesServiceConstructor, BaseGovernanceServiceConstructor, BaseRegistryServiceConstructor, BaseEchoServiceConstructor, BaseEchoService, CachedRelayers, BatchEventsService, BaseEvents, DepositsEvents, WithdrawalsEvents, EncryptedNotesEvents, AllGovernanceEvents, EchoEvents, BatchEventServiceConstructor, BatchEventOnProgress, NetIdType, AllRelayerRegistryEvents, BaseRevenueService, BaseRevenueServiceConstructor, StakeBurnedEvents } from '@tornado/core';
|
||||
import { BaseTornadoService, BaseMultiTornadoService, BaseEncryptedNotesService, BaseGovernanceService, BaseRegistryService, BaseTornadoServiceConstructor, BaseMultiTornadoServiceConstructor, BaseEncryptedNotesServiceConstructor, BaseGovernanceServiceConstructor, BaseRegistryServiceConstructor, BaseEchoServiceConstructor, BaseEchoService, CachedRelayers, BatchEventsService, BaseEvents, DepositsEvents, WithdrawalsEvents, MultiDepositsEvents, MultiWithdrawalsEvents, EncryptedNotesEvents, AllGovernanceEvents, EchoEvents, BatchEventServiceConstructor, BatchEventOnProgress, NetIdType, AllRelayerRegistryEvents, BaseRevenueService, BaseRevenueServiceConstructor, StakeBurnedEvents, BatchBlockOnProgress, BatchBlockServiceConstructor, BatchBlockService, BatchTransactionService } from '@tornado/core';
|
||||
import type { Logger } from 'winston';
|
||||
import { TreeCache } from './treeCache';
|
||||
export interface NodeEventsConstructor extends BatchEventServiceConstructor {
|
||||
@ -12,6 +12,23 @@ export declare class NodeEventsService extends BatchEventsService {
|
||||
getInstanceName: () => string;
|
||||
constructor(serviceConstructor: NodeEventsConstructor);
|
||||
}
|
||||
export interface NodeBlocksConstructor extends BatchBlockServiceConstructor {
|
||||
netId: NetIdType;
|
||||
logger: Logger;
|
||||
getInstanceName: () => string;
|
||||
}
|
||||
export declare class NodeBlocksService extends BatchBlockService {
|
||||
netId: NetIdType;
|
||||
logger: Logger;
|
||||
getInstanceName: () => string;
|
||||
constructor(serviceConstructor: NodeBlocksConstructor);
|
||||
}
|
||||
export declare class NodeTransactionsService extends BatchTransactionService {
|
||||
netId: NetIdType;
|
||||
logger: Logger;
|
||||
getInstanceName: () => string;
|
||||
constructor(serviceConstructor: NodeBlocksConstructor);
|
||||
}
|
||||
export interface NodeTornadoServiceConstructor extends BaseTornadoServiceConstructor {
|
||||
cacheDirectory: string;
|
||||
userDirectory: string;
|
||||
@ -27,10 +44,12 @@ export declare class NodeTornadoService extends BaseTornadoService {
|
||||
treeCache?: TreeCache;
|
||||
constructor(serviceConstructor: NodeTornadoServiceConstructor);
|
||||
updateEventProgress({ fromBlock, toBlock, count }: Parameters<BatchEventOnProgress>[0]): void;
|
||||
updateTransactionProgress({ currentIndex, totalIndex }: Parameters<BatchBlockOnProgress>[0]): void;
|
||||
updateBlockProgress({ currentIndex, totalIndex }: Parameters<BatchBlockOnProgress>[0]): void;
|
||||
getEventsFromDB(): Promise<BaseEvents<DepositsEvents | WithdrawalsEvents>>;
|
||||
getEventsFromCache(): Promise<import("@tornado/core").CachedEvents<DepositsEvents | WithdrawalsEvents>>;
|
||||
validateEvents<S>({ events, lastBlock, hasNewEvents, }: BaseEvents<DepositsEvents | WithdrawalsEvents> & {
|
||||
hasNewEvents?: boolean;
|
||||
validateEvents<S>({ events, newEvents, lastBlock, }: BaseEvents<DepositsEvents | WithdrawalsEvents> & {
|
||||
newEvents: (DepositsEvents | WithdrawalsEvents)[];
|
||||
}): Promise<S>;
|
||||
saveEvents({ events, lastBlock }: BaseEvents<DepositsEvents | WithdrawalsEvents>): Promise<void>;
|
||||
updateEvents<S>(): Promise<{
|
||||
@ -39,6 +58,37 @@ export declare class NodeTornadoService extends BaseTornadoService {
|
||||
validateResult: Awaited<S>;
|
||||
}>;
|
||||
}
|
||||
export interface NodeMultiTornadoServiceConstructor extends BaseMultiTornadoServiceConstructor {
|
||||
cacheDirectory: string;
|
||||
userDirectory: string;
|
||||
nativeCurrency: string;
|
||||
logger: Logger;
|
||||
treeCache?: TreeCache;
|
||||
}
|
||||
export declare class NodeMultiTornadoService extends BaseMultiTornadoService {
|
||||
cacheDirectory: string;
|
||||
userDirectory: string;
|
||||
nativeCurrency: string;
|
||||
logger: Logger;
|
||||
treeCache?: TreeCache;
|
||||
constructor(serviceConstructor: NodeMultiTornadoServiceConstructor);
|
||||
updateEventProgress({ fromBlock, toBlock, count }: Parameters<BatchEventOnProgress>[0]): void;
|
||||
updateTransactionProgress({ currentIndex, totalIndex }: Parameters<BatchBlockOnProgress>[0]): void;
|
||||
updateBlockProgress({ currentIndex, totalIndex }: Parameters<BatchBlockOnProgress>[0]): void;
|
||||
getEventsFromDB(): Promise<BaseEvents<MultiDepositsEvents | MultiWithdrawalsEvents>>;
|
||||
getEventsFromCache(): Promise<import("@tornado/core").CachedEvents<MultiDepositsEvents | MultiWithdrawalsEvents>>;
|
||||
validateEvents<S>({ events, newEvents, lastBlock, }: BaseEvents<MultiDepositsEvents | MultiWithdrawalsEvents> & {
|
||||
newEvents: (MultiDepositsEvents | MultiWithdrawalsEvents)[];
|
||||
}): Promise<S>;
|
||||
saveEvents({ events, newEvents, lastBlock, }: BaseEvents<MultiDepositsEvents | MultiWithdrawalsEvents> & {
|
||||
newEvents: (MultiDepositsEvents | MultiWithdrawalsEvents)[];
|
||||
}): Promise<void>;
|
||||
updateEvents<S>(): Promise<{
|
||||
events: (MultiDepositsEvents | MultiWithdrawalsEvents)[];
|
||||
lastBlock: number;
|
||||
validateResult: Awaited<S>;
|
||||
}>;
|
||||
}
|
||||
export interface NodeEchoServiceConstructor extends BaseEchoServiceConstructor {
|
||||
cacheDirectory: string;
|
||||
userDirectory: string;
|
||||
@ -90,6 +140,7 @@ export declare class NodeGovernanceService extends BaseGovernanceService {
|
||||
logger: Logger;
|
||||
constructor(serviceConstructor: NodeGovernanceServiceConstructor);
|
||||
updateEventProgress({ fromBlock, toBlock, count }: Parameters<BatchEventOnProgress>[0]): void;
|
||||
updateTransactionProgress({ currentIndex, totalIndex }: Parameters<BatchBlockOnProgress>[0]): void;
|
||||
getEventsFromDB(): Promise<BaseEvents<AllGovernanceEvents>>;
|
||||
getEventsFromCache(): Promise<import("@tornado/core").CachedEvents<AllGovernanceEvents>>;
|
||||
saveEvents({ events, lastBlock }: BaseEvents<AllGovernanceEvents>): Promise<void>;
|
||||
@ -133,6 +184,8 @@ export declare class NodeRevenueService extends BaseRevenueService {
|
||||
logger: Logger;
|
||||
constructor(serviceConstructor: NodeRevenueServiceConstructor);
|
||||
updateEventProgress({ fromBlock, toBlock, count }: Parameters<BatchEventOnProgress>[0]): void;
|
||||
updateTransactionProgress({ currentIndex, totalIndex }: Parameters<BatchBlockOnProgress>[0]): void;
|
||||
updateBlockProgress({ currentIndex, totalIndex }: Parameters<BatchBlockOnProgress>[0]): void;
|
||||
getEventsFromDB(): Promise<BaseEvents<StakeBurnedEvents>>;
|
||||
getEventsFromCache(): Promise<import("@tornado/core").CachedEvents<StakeBurnedEvents>>;
|
||||
saveEvents({ events, lastBlock }: BaseEvents<StakeBurnedEvents>): Promise<void>;
|
||||
|
279
lib/services/events.js
vendored
279
lib/services/events.js
vendored
@ -3,10 +3,11 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
||||
return (mod && mod.__esModule) ? mod : { "default": mod };
|
||||
};
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.NodeRevenueService = exports.NodeRegistryService = exports.NodeGovernanceService = exports.NodeEncryptedNotesService = exports.NodeEchoService = exports.NodeTornadoService = exports.NodeEventsService = void 0;
|
||||
exports.NodeRevenueService = exports.NodeRegistryService = exports.NodeGovernanceService = exports.NodeEncryptedNotesService = exports.NodeEchoService = exports.NodeMultiTornadoService = exports.NodeTornadoService = exports.NodeTransactionsService = exports.NodeBlocksService = exports.NodeEventsService = void 0;
|
||||
const path_1 = __importDefault(require("path"));
|
||||
const promises_1 = require("fs/promises");
|
||||
const core_1 = require("@tornado/core");
|
||||
const contracts_1 = require("@tornado/contracts");
|
||||
const data_1 = require("./data");
|
||||
class NodeEventsService extends core_1.BatchEventsService {
|
||||
netId;
|
||||
@ -20,6 +21,30 @@ class NodeEventsService extends core_1.BatchEventsService {
|
||||
}
|
||||
}
|
||||
exports.NodeEventsService = NodeEventsService;
|
||||
class NodeBlocksService extends core_1.BatchBlockService {
|
||||
netId;
|
||||
logger;
|
||||
getInstanceName;
|
||||
constructor(serviceConstructor) {
|
||||
super(serviceConstructor);
|
||||
this.netId = serviceConstructor.netId;
|
||||
this.logger = serviceConstructor.logger;
|
||||
this.getInstanceName = serviceConstructor.getInstanceName;
|
||||
}
|
||||
}
|
||||
exports.NodeBlocksService = NodeBlocksService;
|
||||
class NodeTransactionsService extends core_1.BatchTransactionService {
|
||||
netId;
|
||||
logger;
|
||||
getInstanceName;
|
||||
constructor(serviceConstructor) {
|
||||
super(serviceConstructor);
|
||||
this.netId = serviceConstructor.netId;
|
||||
this.logger = serviceConstructor.logger;
|
||||
this.getInstanceName = serviceConstructor.getInstanceName;
|
||||
}
|
||||
}
|
||||
exports.NodeTransactionsService = NodeTransactionsService;
|
||||
class NodeTornadoService extends core_1.BaseTornadoService {
|
||||
cacheDirectory;
|
||||
userDirectory;
|
||||
@ -41,6 +66,20 @@ class NodeTornadoService extends core_1.BaseTornadoService {
|
||||
logger,
|
||||
getInstanceName: () => `${type.toLowerCase()}s_${netId}_${currency}_${amount}`,
|
||||
});
|
||||
this.batchTransactionService = new NodeTransactionsService({
|
||||
netId,
|
||||
provider,
|
||||
onProgress: this.updateTransactionProgress,
|
||||
logger,
|
||||
getInstanceName: () => `${type.toLowerCase()}s_${netId}_${currency}_${amount}`,
|
||||
});
|
||||
this.batchBlockService = new NodeBlocksService({
|
||||
netId,
|
||||
provider,
|
||||
onProgress: this.updateBlockProgress,
|
||||
logger,
|
||||
getInstanceName: () => `${type.toLowerCase()}s_${netId}_${currency}_${amount}`,
|
||||
});
|
||||
this.treeCache = treeCache;
|
||||
}
|
||||
updateEventProgress({ fromBlock, toBlock, count }) {
|
||||
@ -48,6 +87,16 @@ class NodeTornadoService extends core_1.BaseTornadoService {
|
||||
this.logger.debug(`${this.getInstanceName()}: Fetched ${count} events from ${fromBlock} to ${toBlock}`);
|
||||
}
|
||||
}
|
||||
updateTransactionProgress({ currentIndex, totalIndex }) {
|
||||
if (totalIndex) {
|
||||
this.logger.debug(`${this.getInstanceName()}: Fetched ${currentIndex} deposit txs of ${totalIndex}`);
|
||||
}
|
||||
}
|
||||
updateBlockProgress({ currentIndex, totalIndex }) {
|
||||
if (totalIndex) {
|
||||
this.logger.debug(`${this.getInstanceName()}: Fetched ${currentIndex} withdrawal blocks of ${totalIndex}`);
|
||||
}
|
||||
}
|
||||
async getEventsFromDB() {
|
||||
return await (0, data_1.loadSavedEvents)({
|
||||
name: this.getInstanceName(),
|
||||
@ -61,15 +110,21 @@ class NodeTornadoService extends core_1.BaseTornadoService {
|
||||
deployedBlock: this.deployedBlock,
|
||||
});
|
||||
}
|
||||
async validateEvents({ events, lastBlock, hasNewEvents, }) {
|
||||
async validateEvents({ events, newEvents, lastBlock, }) {
|
||||
const tree = await super.validateEvents({
|
||||
events,
|
||||
newEvents,
|
||||
lastBlock,
|
||||
hasNewEvents,
|
||||
});
|
||||
if (tree && this.currency === this.nativeCurrency && this.treeCache) {
|
||||
const merkleTree = tree;
|
||||
await this.treeCache.createTree(events, merkleTree);
|
||||
await this.treeCache.createTree({
|
||||
netId: this.netId,
|
||||
amount: this.amount,
|
||||
currency: this.currency,
|
||||
events: events,
|
||||
tree: tree,
|
||||
});
|
||||
console.log(`${this.getInstanceName()}: Updated tree cache with root ${(0, core_1.toFixedHex)(BigInt(merkleTree.root))}\n`);
|
||||
}
|
||||
return tree;
|
||||
@ -97,6 +152,186 @@ class NodeTornadoService extends core_1.BaseTornadoService {
|
||||
}
|
||||
}
|
||||
exports.NodeTornadoService = NodeTornadoService;
|
||||
class NodeMultiTornadoService extends core_1.BaseMultiTornadoService {
|
||||
cacheDirectory;
|
||||
userDirectory;
|
||||
nativeCurrency;
|
||||
logger;
|
||||
treeCache;
|
||||
constructor(serviceConstructor) {
|
||||
super(serviceConstructor);
|
||||
const { netId, provider, cacheDirectory, userDirectory, nativeCurrency, logger, treeCache } = serviceConstructor;
|
||||
this.cacheDirectory = cacheDirectory;
|
||||
this.userDirectory = userDirectory;
|
||||
this.nativeCurrency = nativeCurrency;
|
||||
this.logger = logger;
|
||||
this.batchEventsService = new NodeEventsService({
|
||||
netId,
|
||||
provider,
|
||||
contract: this.contract,
|
||||
address: Object.keys(this.instances),
|
||||
onProgress: this.updateEventProgress,
|
||||
logger,
|
||||
getInstanceName: this.getInstanceName,
|
||||
});
|
||||
this.batchTransactionService = new NodeTransactionsService({
|
||||
netId,
|
||||
provider,
|
||||
onProgress: this.updateTransactionProgress,
|
||||
logger,
|
||||
getInstanceName: this.getInstanceName,
|
||||
});
|
||||
this.batchBlockService = new NodeBlocksService({
|
||||
netId,
|
||||
provider,
|
||||
onProgress: this.updateBlockProgress,
|
||||
logger,
|
||||
getInstanceName: this.getInstanceName,
|
||||
});
|
||||
this.treeCache = treeCache;
|
||||
}
|
||||
updateEventProgress({ fromBlock, toBlock, count }) {
|
||||
if (toBlock) {
|
||||
this.logger.debug(`${this.getInstanceName()}: Fetched ${count} events from ${fromBlock} to ${toBlock}`);
|
||||
}
|
||||
}
|
||||
updateTransactionProgress({ currentIndex, totalIndex }) {
|
||||
if (totalIndex) {
|
||||
this.logger.debug(`${this.getInstanceName()}: Fetched ${currentIndex} deposit txs of ${totalIndex}`);
|
||||
}
|
||||
}
|
||||
updateBlockProgress({ currentIndex, totalIndex }) {
|
||||
if (totalIndex) {
|
||||
this.logger.debug(`${this.getInstanceName()}: Fetched ${currentIndex} withdrawal blocks of ${totalIndex}`);
|
||||
}
|
||||
}
|
||||
async getEventsFromDB() {
|
||||
return await (0, data_1.loadSavedEvents)({
|
||||
name: this.getInstanceName(),
|
||||
userDirectory: this.userDirectory,
|
||||
});
|
||||
}
|
||||
async getEventsFromCache() {
|
||||
return await (0, data_1.loadCachedEvents)({
|
||||
name: this.getInstanceName(),
|
||||
cacheDirectory: this.cacheDirectory,
|
||||
deployedBlock: this.deployedBlock,
|
||||
});
|
||||
}
|
||||
async validateEvents({ events, newEvents, lastBlock, }) {
|
||||
const tree = await super.validateEvents({
|
||||
events,
|
||||
newEvents,
|
||||
lastBlock,
|
||||
});
|
||||
if (this.merkleTreeService && this.treeCache) {
|
||||
const instancesWithNewEvents = [
|
||||
...new Set(newEvents.filter(({ event }) => event === 'Deposit').map(({ instanceAddress }) => instanceAddress)),
|
||||
];
|
||||
for (const instance of instancesWithNewEvents) {
|
||||
const { amount, currency } = this.instances[instance];
|
||||
// Only create cached tree for native currencies
|
||||
if (currency !== this.nativeCurrency) {
|
||||
continue;
|
||||
}
|
||||
const depositEvents = events.filter(({ instanceAddress, event }) => instanceAddress === instance && event === 'Deposit');
|
||||
// Create tree cache with existing tree
|
||||
if (tree && this.merkleTreeService.Tornado.target === instance) {
|
||||
await this.treeCache.createTree({
|
||||
netId: this.netId,
|
||||
amount,
|
||||
currency,
|
||||
events: depositEvents,
|
||||
tree: tree,
|
||||
});
|
||||
// Create new tree cache
|
||||
}
|
||||
else {
|
||||
const merkleTreeService = new core_1.MerkleTreeService({
|
||||
netId: this.netId,
|
||||
amount,
|
||||
currency,
|
||||
Tornado: contracts_1.Tornado__factory.connect(instance, this.provider),
|
||||
merkleWorkerPath: this.merkleTreeService.merkleWorkerPath,
|
||||
});
|
||||
const tree = await merkleTreeService.verifyTree(depositEvents);
|
||||
await this.treeCache.createTree({
|
||||
netId: this.netId,
|
||||
amount,
|
||||
currency,
|
||||
events: depositEvents,
|
||||
tree,
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
return tree;
|
||||
}
|
||||
async saveEvents({ events, newEvents, lastBlock, }) {
|
||||
const instancesWithNewEvents = [...new Set(newEvents.map(({ instanceAddress }) => instanceAddress))];
|
||||
for (const instance of instancesWithNewEvents) {
|
||||
const { currency, amount } = this.instances[instance];
|
||||
const { depositEvents, withdrawalEvents } = events.reduce((acc, curr) => {
|
||||
if (curr.instanceAddress === instance) {
|
||||
if (curr.event === 'Deposit') {
|
||||
acc.depositEvents.push({
|
||||
...curr,
|
||||
event: undefined,
|
||||
instanceAddress: undefined,
|
||||
});
|
||||
}
|
||||
else if (curr.event === 'Withdrawal') {
|
||||
acc.withdrawalEvents.push({
|
||||
...curr,
|
||||
event: undefined,
|
||||
instanceAddress: undefined,
|
||||
relayerAddress: undefined,
|
||||
});
|
||||
}
|
||||
}
|
||||
return acc;
|
||||
}, {
|
||||
depositEvents: [],
|
||||
withdrawalEvents: [],
|
||||
});
|
||||
await (0, promises_1.writeFile)(path_1.default.join(this.userDirectory, `recent_deposits_${this.netId}_${currency}_${amount}.json`), JSON.stringify(depositEvents.slice(depositEvents.length - 10).reverse(), null, 2) + '\n');
|
||||
await (0, data_1.saveUserFile)({
|
||||
fileName: `deposits_${this.netId}_${currency}_${amount}.json`,
|
||||
userDirectory: this.userDirectory,
|
||||
dataString: JSON.stringify(depositEvents, null, 2) + '\n',
|
||||
lastBlock,
|
||||
});
|
||||
await (0, data_1.saveUserFile)({
|
||||
fileName: `withdrawals_${this.netId}_${currency}_${amount}.json`,
|
||||
userDirectory: this.userDirectory,
|
||||
dataString: JSON.stringify(withdrawalEvents, null, 2) + '\n',
|
||||
lastBlock,
|
||||
});
|
||||
console.log(`\nSaved ${this.netId}_${currency}_${amount}.json event: ` +
|
||||
`${depositEvents.length} deposits ${withdrawalEvents.length} withdrawals\n`);
|
||||
}
|
||||
await (0, data_1.saveUserFile)({
|
||||
fileName: this.getInstanceName() + '.json',
|
||||
userDirectory: this.userDirectory,
|
||||
dataString: JSON.stringify(events, null, 2) + '\n',
|
||||
lastBlock,
|
||||
});
|
||||
}
|
||||
async updateEvents() {
|
||||
const { events, lastBlock, validateResult } = await super.updateEvents();
|
||||
await (0, data_1.saveLastBlock)({
|
||||
fileName: this.getInstanceName(),
|
||||
userDirectory: this.userDirectory,
|
||||
lastBlock,
|
||||
});
|
||||
return {
|
||||
events,
|
||||
lastBlock,
|
||||
validateResult,
|
||||
};
|
||||
}
|
||||
}
|
||||
exports.NodeMultiTornadoService = NodeMultiTornadoService;
|
||||
class NodeEchoService extends core_1.BaseEchoService {
|
||||
cacheDirectory;
|
||||
userDirectory;
|
||||
@ -237,12 +472,24 @@ class NodeGovernanceService extends core_1.BaseGovernanceService {
|
||||
logger,
|
||||
getInstanceName: this.getInstanceName,
|
||||
});
|
||||
this.batchTransactionService = new NodeTransactionsService({
|
||||
netId,
|
||||
provider,
|
||||
onProgress: this.updateTransactionProgress,
|
||||
logger,
|
||||
getInstanceName: this.getInstanceName,
|
||||
});
|
||||
}
|
||||
updateEventProgress({ fromBlock, toBlock, count }) {
|
||||
if (toBlock) {
|
||||
this.logger.debug(`${this.getInstanceName()}: Fetched ${count} events from ${fromBlock} to ${toBlock}`);
|
||||
}
|
||||
}
|
||||
updateTransactionProgress({ currentIndex, totalIndex }) {
|
||||
if (totalIndex) {
|
||||
this.logger.debug(`${this.getInstanceName()}: Fetched ${currentIndex} governance txs of ${totalIndex}`);
|
||||
}
|
||||
}
|
||||
async getEventsFromDB() {
|
||||
return await (0, data_1.loadSavedEvents)({
|
||||
name: this.getInstanceName(),
|
||||
@ -423,12 +670,36 @@ class NodeRevenueService extends core_1.BaseRevenueService {
|
||||
logger,
|
||||
getInstanceName: this.getInstanceName,
|
||||
});
|
||||
this.batchTransactionService = new NodeTransactionsService({
|
||||
netId,
|
||||
provider,
|
||||
onProgress: this.updateTransactionProgress,
|
||||
logger,
|
||||
getInstanceName: this.getInstanceName,
|
||||
});
|
||||
this.batchBlockService = new NodeBlocksService({
|
||||
netId,
|
||||
provider,
|
||||
onProgress: this.updateBlockProgress,
|
||||
logger,
|
||||
getInstanceName: this.getInstanceName,
|
||||
});
|
||||
}
|
||||
updateEventProgress({ fromBlock, toBlock, count }) {
|
||||
if (toBlock) {
|
||||
this.logger.debug(`${this.getInstanceName()}: Fetched ${count} events from ${fromBlock} to ${toBlock}`);
|
||||
}
|
||||
}
|
||||
updateTransactionProgress({ currentIndex, totalIndex }) {
|
||||
if (totalIndex) {
|
||||
this.logger.debug(`${this.getInstanceName()}: Fetched ${currentIndex} txs of ${totalIndex}`);
|
||||
}
|
||||
}
|
||||
updateBlockProgress({ currentIndex, totalIndex }) {
|
||||
if (totalIndex) {
|
||||
this.logger.debug(`${this.getInstanceName()}: Fetched ${currentIndex} blocks of ${totalIndex}`);
|
||||
}
|
||||
}
|
||||
async getEventsFromDB() {
|
||||
return await (0, data_1.loadSavedEvents)({
|
||||
name: this.getInstanceName(),
|
||||
|
33
lib/services/router.js
vendored
33
lib/services/router.js
vendored
@ -116,28 +116,39 @@ async function handleGetJob(router, req, reply) {
|
||||
async function handleEvents(router, netId, req, reply) {
|
||||
const { relayerConfig: { userEventsDir: userDirectory }, } = router;
|
||||
const { type, currency, amount, fromBlock, recent } = req.body;
|
||||
const name = [core_1.DEPOSIT, core_1.WITHDRAWAL].includes(type) ? `${type}s_${netId}_${currency}_${amount}` : `${type}_${netId}`;
|
||||
// Can return 0 events but we just return error codes here
|
||||
const name = ['deposit', 'withdrawal'].includes(type)
|
||||
? `${type}s_${netId}_${currency}_${amount}`
|
||||
: `${type}_${netId}`;
|
||||
// Return 0 length events if not exist (likely 0 events, can be checked by lastSyncBlock === fromBlock)
|
||||
if (!(await (0, data_1.existsAsync)(path_1.default.join(userDirectory, `${name}.json`)))) {
|
||||
reply.code(404).send(`Events ${name} not found!`);
|
||||
reply.send({
|
||||
events: [],
|
||||
lastSyncBlock: fromBlock,
|
||||
});
|
||||
return;
|
||||
}
|
||||
const { syncManagerStatus } = await (0, routerMsg_1.sendMessage)(router, { type: 'status' });
|
||||
const lastSyncBlock = Number([core_1.DEPOSIT, core_1.WITHDRAWAL].includes(type)
|
||||
? syncManagerStatus.cachedEvents[netId]?.instances?.[String(currency)]?.[String(amount)]?.[`${type}s`]?.lastBlock
|
||||
const lastSyncBlock = Number(['deposit', 'withdrawal'].includes(type)
|
||||
? syncManagerStatus.cachedEvents[netId]?.tornado?.lastBlock
|
||||
: syncManagerStatus.cachedEvents[netId]?.[String(type)]?.lastBlock);
|
||||
if (type === 'deposit' && recent) {
|
||||
const { events } = await (0, data_1.loadSavedEvents)({
|
||||
name: 'recent_' + name,
|
||||
userDirectory,
|
||||
});
|
||||
reply.send({
|
||||
events,
|
||||
lastSyncBlock,
|
||||
});
|
||||
return;
|
||||
}
|
||||
const { events } = await (0, data_1.loadSavedEvents)({
|
||||
name,
|
||||
userDirectory,
|
||||
});
|
||||
if (recent) {
|
||||
reply.send({
|
||||
events: events.slice(-10).sort((a, b) => {
|
||||
if (a.blockNumber === b.blockNumber) {
|
||||
return b.logIndex - a.logIndex;
|
||||
}
|
||||
return b.blockNumber - a.blockNumber;
|
||||
}),
|
||||
events: events.slice(events.length - 10).reverse(),
|
||||
lastSyncBlock,
|
||||
});
|
||||
return;
|
||||
|
4
lib/services/schema.js
vendored
4
lib/services/schema.js
vendored
@ -139,7 +139,7 @@ function getEventsKeyword(netId) {
|
||||
validate: (schema, data) => {
|
||||
try {
|
||||
const { type, currency, amount } = data;
|
||||
if ([core_1.DEPOSIT, core_1.WITHDRAWAL].includes(type)) {
|
||||
if (['deposit', 'withdrawal'].includes(type)) {
|
||||
const instanceAddress = config.tokens[String(currency)]?.instanceAddress?.[String(amount)];
|
||||
if (!instanceAddress) {
|
||||
return false;
|
||||
@ -159,7 +159,7 @@ function getEventsKeyword(netId) {
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return ['echo', 'encrypted_notes'].includes(type);
|
||||
return ['tornado', 'echo', 'encrypted_notes'].includes(type);
|
||||
}
|
||||
catch {
|
||||
return false;
|
||||
|
14
lib/services/sync.d.ts
vendored
14
lib/services/sync.d.ts
vendored
@ -2,18 +2,8 @@ import type { Provider } from 'ethers';
|
||||
import type { Logger } from 'winston';
|
||||
import { NetIdType, TokenPriceOracle, TornadoFeeOracle, TovarishEventsStatus, TovarishSyncStatus } from '@tornado/core';
|
||||
import { RelayerConfig } from '../config';
|
||||
import { NodeEchoService, NodeEncryptedNotesService, NodeGovernanceService, NodeRegistryService, NodeRevenueService, NodeTornadoService } from './events';
|
||||
import { NodeEchoService, NodeEncryptedNotesService, NodeGovernanceService, NodeRegistryService, NodeRevenueService, NodeMultiTornadoService } from './events';
|
||||
import { ErrorTypes, ErrorMessages } from './error';
|
||||
export interface AmountsServices {
|
||||
depositsService: NodeTornadoService;
|
||||
withdrawalsService: NodeTornadoService;
|
||||
}
|
||||
export interface CurrencyServices {
|
||||
[index: string]: AmountsServices;
|
||||
}
|
||||
export interface TornadoServices {
|
||||
[index: string]: CurrencyServices;
|
||||
}
|
||||
export interface Services {
|
||||
provider: Provider;
|
||||
tokenPriceOracle: TokenPriceOracle;
|
||||
@ -23,7 +13,7 @@ export interface Services {
|
||||
revenueService?: NodeRevenueService;
|
||||
echoService: NodeEchoService;
|
||||
encryptedNotesService: NodeEncryptedNotesService;
|
||||
tornadoServices: TornadoServices;
|
||||
tornadoServices: NodeMultiTornadoService;
|
||||
}
|
||||
export interface CachedServices {
|
||||
[index: NetIdType]: Services;
|
||||
|
76
lib/services/sync.js
vendored
76
lib/services/sync.js
vendored
@ -18,7 +18,7 @@ function setupServices(syncManager) {
|
||||
const config = (0, core_1.getConfig)(netId);
|
||||
const rpcUrl = relayerConfig.rpcUrls[netId];
|
||||
const provider = (0, core_1.getProviderWithNetId)(netId, rpcUrl, config);
|
||||
const { tokens, nativeCurrency, routerContract, echoContract, registryContract, aggregatorContract, reverseRecordsContract, governanceContract, multicallContract, offchainOracleContract, ovmGasPriceOracleContract, deployedBlock, constants: { GOVERNANCE_BLOCK, REGISTRY_BLOCK, NOTE_ACCOUNT_BLOCK, ENCRYPTED_NOTES_BLOCK }, } = config;
|
||||
const { nativeCurrency, routerContract, echoContract, registryContract, aggregatorContract, reverseRecordsContract, governanceContract, multicallContract, offchainOracleContract, ovmGasPriceOracleContract, deployedBlock, constants: { GOVERNANCE_BLOCK, REGISTRY_BLOCK, NOTE_ACCOUNT_BLOCK, ENCRYPTED_NOTES_BLOCK }, } = config;
|
||||
if (!syncStatus[netId]) {
|
||||
syncStatus[netId] = {
|
||||
events: false,
|
||||
@ -85,49 +85,29 @@ function setupServices(syncManager) {
|
||||
userDirectory,
|
||||
logger,
|
||||
});
|
||||
services.tornadoServices = {};
|
||||
for (const currency of (0, core_1.getActiveTokens)(config)) {
|
||||
const currencyConfig = tokens[currency];
|
||||
const currencyService = (services.tornadoServices[currency] = {});
|
||||
for (const [amount, instanceAddress] of Object.entries(currencyConfig.instanceAddress)) {
|
||||
const Tornado = contracts_1.Tornado__factory.connect(instanceAddress, provider);
|
||||
const amountService = (currencyService[amount] = {});
|
||||
const TornadoServiceConstructor = {
|
||||
const instances = (0, core_1.getMultiInstances)(netId, config);
|
||||
const [firstInstance, { amount, currency }] = Object.entries(instances)[0];
|
||||
services.tornadoServices = new events_1.NodeMultiTornadoService({
|
||||
netId,
|
||||
provider,
|
||||
Tornado,
|
||||
amount,
|
||||
currency,
|
||||
instances,
|
||||
deployedBlock,
|
||||
cacheDirectory,
|
||||
userDirectory,
|
||||
nativeCurrency,
|
||||
logger,
|
||||
};
|
||||
amountService.depositsService = new events_1.NodeTornadoService({
|
||||
...TornadoServiceConstructor,
|
||||
merkleTreeService: new core_1.MerkleTreeService({
|
||||
netId,
|
||||
amount,
|
||||
currency,
|
||||
Tornado,
|
||||
Tornado: contracts_1.Tornado__factory.connect(firstInstance, provider),
|
||||
merkleWorkerPath,
|
||||
}),
|
||||
treeCache: new treeCache_1.TreeCache({
|
||||
netId,
|
||||
amount,
|
||||
currency,
|
||||
userDirectory: userTreeDir,
|
||||
}),
|
||||
optionalTree: true,
|
||||
type: 'Deposit',
|
||||
nativeCurrency,
|
||||
cacheDirectory,
|
||||
userDirectory,
|
||||
logger,
|
||||
});
|
||||
amountService.withdrawalsService = new events_1.NodeTornadoService({
|
||||
...TornadoServiceConstructor,
|
||||
type: 'Withdrawal',
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
syncManager.cachedServices = cachedServices;
|
||||
}
|
||||
@ -215,12 +195,11 @@ async function syncNetworkEvents(syncManager, netId) {
|
||||
logger.info(`${netId}: Syncing events from block ${await provider.getBlockNumber()}`);
|
||||
const eventsStatus = {
|
||||
governance: governanceService ? {} : undefined,
|
||||
registered: registryService ? {} : undefined,
|
||||
registry: registryService ? {} : undefined,
|
||||
revenue: revenueService ? {} : undefined,
|
||||
echo: {},
|
||||
encrypted_notes: {},
|
||||
instances: {},
|
||||
tornado: {},
|
||||
};
|
||||
if (governanceService) {
|
||||
const { events, lastBlock } = await governanceService.updateEvents();
|
||||
@ -241,11 +220,6 @@ async function syncNetworkEvents(syncManager, netId) {
|
||||
}
|
||||
{
|
||||
const { lastBlock, timestamp, relayers } = await registryService.updateRelayers();
|
||||
eventsStatus.registered = {
|
||||
lastBlock,
|
||||
timestamp,
|
||||
relayers: relayers.length,
|
||||
};
|
||||
logger.info(`${netId}: Updated registry relayers (total: ${relayers.length}, block: ${lastBlock}, timestamp: ${timestamp})`);
|
||||
}
|
||||
}
|
||||
@ -269,30 +243,12 @@ async function syncNetworkEvents(syncManager, netId) {
|
||||
lastBlock: encryptedNotesEvents.lastBlock,
|
||||
};
|
||||
logger.info(`${netId}: Updated encrypted notes events (total: ${encryptedNotesEvents.events.length}, block: ${encryptedNotesEvents.lastBlock})`);
|
||||
const currencies = Object.keys(tornadoServices);
|
||||
for (const currency of currencies) {
|
||||
const currencyStatus = (eventsStatus.instances[currency] = {});
|
||||
const amounts = Object.keys(tornadoServices[currency]);
|
||||
for (const amount of amounts) {
|
||||
const instanceStatus = (currencyStatus[amount] = {
|
||||
deposits: {},
|
||||
withdrawals: {},
|
||||
});
|
||||
const { depositsService, withdrawalsService } = tornadoServices[currency][amount];
|
||||
const depositEvents = await depositsService.updateEvents();
|
||||
instanceStatus.deposits = {
|
||||
events: depositEvents.events.length,
|
||||
lastBlock: depositEvents.lastBlock,
|
||||
const tornadoEvents = await tornadoServices.updateEvents();
|
||||
eventsStatus.tornado = {
|
||||
events: tornadoEvents.events.length,
|
||||
lastBlock: tornadoEvents.lastBlock,
|
||||
};
|
||||
logger.info(`${netId}: Updated ${currency} ${amount} Tornado deposit events (total: ${depositEvents.events.length}, block: ${depositEvents.lastBlock})`);
|
||||
const withdrawalEvents = await withdrawalsService.updateEvents();
|
||||
instanceStatus.withdrawals = {
|
||||
events: withdrawalEvents.events.length,
|
||||
lastBlock: withdrawalEvents.lastBlock,
|
||||
};
|
||||
logger.info(`${netId}: Updated ${currency} ${amount} Tornado withdrawal events (total: ${withdrawalEvents.events.length}, block: ${withdrawalEvents.lastBlock})`);
|
||||
}
|
||||
}
|
||||
logger.info(`${netId}: Updated tornado events (total: ${tornadoEvents.events.length}, block: ${tornadoEvents.lastBlock})`);
|
||||
cachedEvents[netId] = eventsStatus;
|
||||
syncStatus[netId].events = true;
|
||||
logger.info(`${netId}: Synced all events`);
|
||||
|
20
lib/services/treeCache.d.ts
vendored
20
lib/services/treeCache.d.ts
vendored
@ -7,9 +7,6 @@ import { MerkleTree } from '@tornado/fixed-merkle-tree';
|
||||
import { DepositsEvents } from '@tornado/core';
|
||||
import type { NetIdType } from '@tornado/core';
|
||||
export interface TreeCacheConstructor {
|
||||
netId: NetIdType;
|
||||
amount: string;
|
||||
currency: string;
|
||||
userDirectory: string;
|
||||
PARTS_COUNT?: number;
|
||||
LEAVES?: number;
|
||||
@ -24,12 +21,19 @@ export interface treeMetadata {
|
||||
leafIndex: number;
|
||||
}
|
||||
export declare class TreeCache {
|
||||
userDirectory: string;
|
||||
PARTS_COUNT: number;
|
||||
constructor({ userDirectory, PARTS_COUNT }: TreeCacheConstructor);
|
||||
static getInstanceName({ netId, amount, currency, }: {
|
||||
netId: NetIdType;
|
||||
amount: string;
|
||||
currency: string;
|
||||
userDirectory: string;
|
||||
PARTS_COUNT: number;
|
||||
constructor({ netId, amount, currency, userDirectory, PARTS_COUNT }: TreeCacheConstructor);
|
||||
getInstanceName(): string;
|
||||
createTree(events: DepositsEvents[], tree: MerkleTree): Promise<void>;
|
||||
}): string;
|
||||
createTree({ netId, amount, currency, events, tree, }: {
|
||||
netId: NetIdType;
|
||||
amount: string;
|
||||
currency: string;
|
||||
events: DepositsEvents[];
|
||||
tree: MerkleTree;
|
||||
}): Promise<void>;
|
||||
}
|
||||
|
21
lib/services/treeCache.js
vendored
21
lib/services/treeCache.js
vendored
@ -7,24 +7,19 @@ exports.TreeCache = void 0;
|
||||
const bloomfilter_js_1 = __importDefault(require("bloomfilter.js"));
|
||||
const data_1 = require("./data");
|
||||
class TreeCache {
|
||||
netId;
|
||||
amount;
|
||||
currency;
|
||||
userDirectory;
|
||||
PARTS_COUNT;
|
||||
constructor({ netId, amount, currency, userDirectory, PARTS_COUNT = 4 }) {
|
||||
this.netId = netId;
|
||||
this.amount = amount;
|
||||
this.currency = currency;
|
||||
constructor({ userDirectory, PARTS_COUNT = 4 }) {
|
||||
this.userDirectory = userDirectory;
|
||||
this.PARTS_COUNT = PARTS_COUNT;
|
||||
}
|
||||
getInstanceName() {
|
||||
return `deposits_${this.netId}_${this.currency}_${this.amount}`;
|
||||
static getInstanceName({ netId, amount, currency, }) {
|
||||
return `deposits_${netId}_${currency}_${amount}`;
|
||||
}
|
||||
async createTree(events, tree) {
|
||||
async createTree({ netId, amount, currency, events, tree, }) {
|
||||
const bloom = new bloomfilter_js_1.default(events.length);
|
||||
console.log(`Creating cached tree for ${this.getInstanceName()}\n`);
|
||||
const instance = TreeCache.getInstanceName({ netId, amount, currency });
|
||||
console.log(`Creating cached tree for ${instance}\n`);
|
||||
// events indexed by commitment
|
||||
const eventsData = events.reduce((acc, { leafIndex, commitment, ...rest }, i) => {
|
||||
if (leafIndex !== i) {
|
||||
@ -46,7 +41,7 @@ class TreeCache {
|
||||
...slice,
|
||||
metadata,
|
||||
}, null, 2) + '\n';
|
||||
const fileName = `${this.getInstanceName()}_slice${index + 1}.json`;
|
||||
const fileName = `${instance}_slice${index + 1}.json`;
|
||||
await (0, data_1.saveUserFile)({
|
||||
fileName,
|
||||
userDirectory: this.userDirectory,
|
||||
@ -54,7 +49,7 @@ class TreeCache {
|
||||
});
|
||||
}));
|
||||
const dataString = bloom.serialize() + '\n';
|
||||
const fileName = `${this.getInstanceName()}_bloom.json`;
|
||||
const fileName = `${instance}_bloom.json`;
|
||||
await (0, data_1.saveUserFile)({
|
||||
fileName,
|
||||
userDirectory: this.userDirectory,
|
||||
|
@ -14,7 +14,7 @@
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@fastify/cors": "^10.0.1",
|
||||
"@tornado/core": "git+https://git.tornado.ws/tornadocontrib/tornado-core.git#94a62e6193c99457a8dfae0d8684bee299cb1097",
|
||||
"@tornado/core": "git+https://git.tornado.ws/tornadocontrib/tornado-core.git#68fcf07c2a344a1f7f74895301f362aa059b53e2",
|
||||
"bloomfilter.js": "^1.0.2",
|
||||
"dotenv": "^16.4.5",
|
||||
"fastify": "^5.0.0",
|
||||
|
@ -98,6 +98,6 @@ export function getRelayerConfig(): RelayerConfig {
|
||||
cacheDir: path.join(STATIC_DIR, './events'),
|
||||
userEventsDir: path.join(USER_DIR, './events'),
|
||||
userTreeDir: path.join(USER_DIR, './trees'),
|
||||
syncInterval: Number(process.env.SYNC_INTERVAL || 120),
|
||||
syncInterval: Number(process.env.SYNC_INTERVAL || 180),
|
||||
};
|
||||
}
|
||||
|
@ -1,11 +1,13 @@
|
||||
import path from 'path';
|
||||
import { readFile } from 'fs/promises';
|
||||
import { readFile, writeFile } from 'fs/promises';
|
||||
import {
|
||||
BaseTornadoService,
|
||||
BaseMultiTornadoService,
|
||||
BaseEncryptedNotesService,
|
||||
BaseGovernanceService,
|
||||
BaseRegistryService,
|
||||
BaseTornadoServiceConstructor,
|
||||
BaseMultiTornadoServiceConstructor,
|
||||
BaseEncryptedNotesServiceConstructor,
|
||||
BaseGovernanceServiceConstructor,
|
||||
BaseRegistryServiceConstructor,
|
||||
@ -17,6 +19,9 @@ import {
|
||||
BaseEvents,
|
||||
DepositsEvents,
|
||||
WithdrawalsEvents,
|
||||
MultiDepositsEvents,
|
||||
MultiWithdrawalsEvents,
|
||||
MerkleTreeService,
|
||||
EncryptedNotesEvents,
|
||||
AllGovernanceEvents,
|
||||
EchoEvents,
|
||||
@ -27,7 +32,12 @@ import {
|
||||
BaseRevenueService,
|
||||
BaseRevenueServiceConstructor,
|
||||
StakeBurnedEvents,
|
||||
BatchBlockOnProgress,
|
||||
BatchBlockServiceConstructor,
|
||||
BatchBlockService,
|
||||
BatchTransactionService,
|
||||
} from '@tornado/core';
|
||||
import { Tornado__factory } from '@tornado/contracts';
|
||||
import type { MerkleTree } from '@tornado/fixed-merkle-tree';
|
||||
import type { Logger } from 'winston';
|
||||
import { saveUserFile, loadSavedEvents, loadCachedEvents, existsAsync, saveLastBlock } from './data';
|
||||
@ -53,6 +63,40 @@ export class NodeEventsService extends BatchEventsService {
|
||||
}
|
||||
}
|
||||
|
||||
export interface NodeBlocksConstructor extends BatchBlockServiceConstructor {
|
||||
netId: NetIdType;
|
||||
logger: Logger;
|
||||
getInstanceName: () => string;
|
||||
}
|
||||
|
||||
export class NodeBlocksService extends BatchBlockService {
|
||||
netId: NetIdType;
|
||||
logger: Logger;
|
||||
getInstanceName: () => string;
|
||||
|
||||
constructor(serviceConstructor: NodeBlocksConstructor) {
|
||||
super(serviceConstructor);
|
||||
|
||||
this.netId = serviceConstructor.netId;
|
||||
this.logger = serviceConstructor.logger;
|
||||
this.getInstanceName = serviceConstructor.getInstanceName;
|
||||
}
|
||||
}
|
||||
|
||||
export class NodeTransactionsService extends BatchTransactionService {
|
||||
netId: NetIdType;
|
||||
logger: Logger;
|
||||
getInstanceName: () => string;
|
||||
|
||||
constructor(serviceConstructor: NodeBlocksConstructor) {
|
||||
super(serviceConstructor);
|
||||
|
||||
this.netId = serviceConstructor.netId;
|
||||
this.logger = serviceConstructor.logger;
|
||||
this.getInstanceName = serviceConstructor.getInstanceName;
|
||||
}
|
||||
}
|
||||
|
||||
export interface NodeTornadoServiceConstructor extends BaseTornadoServiceConstructor {
|
||||
cacheDirectory: string;
|
||||
userDirectory: string;
|
||||
@ -102,6 +146,22 @@ export class NodeTornadoService extends BaseTornadoService {
|
||||
getInstanceName: () => `${type.toLowerCase()}s_${netId}_${currency}_${amount}`,
|
||||
});
|
||||
|
||||
this.batchTransactionService = new NodeTransactionsService({
|
||||
netId,
|
||||
provider,
|
||||
onProgress: this.updateTransactionProgress,
|
||||
logger,
|
||||
getInstanceName: () => `${type.toLowerCase()}s_${netId}_${currency}_${amount}`,
|
||||
});
|
||||
|
||||
this.batchBlockService = new NodeBlocksService({
|
||||
netId,
|
||||
provider,
|
||||
onProgress: this.updateBlockProgress,
|
||||
logger,
|
||||
getInstanceName: () => `${type.toLowerCase()}s_${netId}_${currency}_${amount}`,
|
||||
});
|
||||
|
||||
this.treeCache = treeCache;
|
||||
}
|
||||
|
||||
@ -111,6 +171,18 @@ export class NodeTornadoService extends BaseTornadoService {
|
||||
}
|
||||
}
|
||||
|
||||
updateTransactionProgress({ currentIndex, totalIndex }: Parameters<BatchBlockOnProgress>[0]) {
|
||||
if (totalIndex) {
|
||||
this.logger.debug(`${this.getInstanceName()}: Fetched ${currentIndex} deposit txs of ${totalIndex}`);
|
||||
}
|
||||
}
|
||||
|
||||
updateBlockProgress({ currentIndex, totalIndex }: Parameters<BatchBlockOnProgress>[0]) {
|
||||
if (totalIndex) {
|
||||
this.logger.debug(`${this.getInstanceName()}: Fetched ${currentIndex} withdrawal blocks of ${totalIndex}`);
|
||||
}
|
||||
}
|
||||
|
||||
async getEventsFromDB() {
|
||||
return await loadSavedEvents<DepositsEvents | WithdrawalsEvents>({
|
||||
name: this.getInstanceName(),
|
||||
@ -128,21 +200,27 @@ export class NodeTornadoService extends BaseTornadoService {
|
||||
|
||||
async validateEvents<S>({
|
||||
events,
|
||||
newEvents,
|
||||
lastBlock,
|
||||
hasNewEvents,
|
||||
}: BaseEvents<DepositsEvents | WithdrawalsEvents> & {
|
||||
hasNewEvents?: boolean;
|
||||
newEvents: (DepositsEvents | WithdrawalsEvents)[];
|
||||
}): Promise<S> {
|
||||
const tree = await super.validateEvents<S>({
|
||||
events,
|
||||
newEvents,
|
||||
lastBlock,
|
||||
hasNewEvents,
|
||||
});
|
||||
|
||||
if (tree && this.currency === this.nativeCurrency && this.treeCache) {
|
||||
const merkleTree = tree as unknown as MerkleTree;
|
||||
|
||||
await this.treeCache.createTree(events as DepositsEvents[], merkleTree);
|
||||
await this.treeCache.createTree({
|
||||
netId: this.netId,
|
||||
amount: this.amount,
|
||||
currency: this.currency,
|
||||
events: events as DepositsEvents[],
|
||||
tree: tree as unknown as MerkleTree,
|
||||
});
|
||||
|
||||
console.log(
|
||||
`${this.getInstanceName()}: Updated tree cache with root ${toFixedHex(BigInt(merkleTree.root))}\n`,
|
||||
@ -178,6 +256,253 @@ export class NodeTornadoService extends BaseTornadoService {
|
||||
}
|
||||
}
|
||||
|
||||
export interface NodeMultiTornadoServiceConstructor extends BaseMultiTornadoServiceConstructor {
|
||||
cacheDirectory: string;
|
||||
userDirectory: string;
|
||||
nativeCurrency: string;
|
||||
logger: Logger;
|
||||
treeCache?: TreeCache;
|
||||
}
|
||||
|
||||
export class NodeMultiTornadoService extends BaseMultiTornadoService {
|
||||
cacheDirectory: string;
|
||||
userDirectory: string;
|
||||
|
||||
nativeCurrency: string;
|
||||
logger: Logger;
|
||||
|
||||
treeCache?: TreeCache;
|
||||
|
||||
constructor(serviceConstructor: NodeMultiTornadoServiceConstructor) {
|
||||
super(serviceConstructor);
|
||||
|
||||
const { netId, provider, cacheDirectory, userDirectory, nativeCurrency, logger, treeCache } =
|
||||
serviceConstructor;
|
||||
|
||||
this.cacheDirectory = cacheDirectory;
|
||||
this.userDirectory = userDirectory;
|
||||
this.nativeCurrency = nativeCurrency;
|
||||
|
||||
this.logger = logger;
|
||||
|
||||
this.batchEventsService = new NodeEventsService({
|
||||
netId,
|
||||
provider,
|
||||
contract: this.contract,
|
||||
address: Object.keys(this.instances),
|
||||
onProgress: this.updateEventProgress,
|
||||
logger,
|
||||
getInstanceName: this.getInstanceName,
|
||||
});
|
||||
|
||||
this.batchTransactionService = new NodeTransactionsService({
|
||||
netId,
|
||||
provider,
|
||||
onProgress: this.updateTransactionProgress,
|
||||
logger,
|
||||
getInstanceName: this.getInstanceName,
|
||||
});
|
||||
|
||||
this.batchBlockService = new NodeBlocksService({
|
||||
netId,
|
||||
provider,
|
||||
onProgress: this.updateBlockProgress,
|
||||
logger,
|
||||
getInstanceName: this.getInstanceName,
|
||||
});
|
||||
|
||||
this.treeCache = treeCache;
|
||||
}
|
||||
|
||||
updateEventProgress({ fromBlock, toBlock, count }: Parameters<BatchEventOnProgress>[0]) {
|
||||
if (toBlock) {
|
||||
this.logger.debug(`${this.getInstanceName()}: Fetched ${count} events from ${fromBlock} to ${toBlock}`);
|
||||
}
|
||||
}
|
||||
|
||||
updateTransactionProgress({ currentIndex, totalIndex }: Parameters<BatchBlockOnProgress>[0]) {
|
||||
if (totalIndex) {
|
||||
this.logger.debug(`${this.getInstanceName()}: Fetched ${currentIndex} deposit txs of ${totalIndex}`);
|
||||
}
|
||||
}
|
||||
|
||||
updateBlockProgress({ currentIndex, totalIndex }: Parameters<BatchBlockOnProgress>[0]) {
|
||||
if (totalIndex) {
|
||||
this.logger.debug(`${this.getInstanceName()}: Fetched ${currentIndex} withdrawal blocks of ${totalIndex}`);
|
||||
}
|
||||
}
|
||||
|
||||
async getEventsFromDB() {
|
||||
return await loadSavedEvents<MultiDepositsEvents | MultiWithdrawalsEvents>({
|
||||
name: this.getInstanceName(),
|
||||
userDirectory: this.userDirectory,
|
||||
});
|
||||
}
|
||||
|
||||
async getEventsFromCache() {
|
||||
return await loadCachedEvents<MultiDepositsEvents | MultiWithdrawalsEvents>({
|
||||
name: this.getInstanceName(),
|
||||
cacheDirectory: this.cacheDirectory,
|
||||
deployedBlock: this.deployedBlock,
|
||||
});
|
||||
}
|
||||
|
||||
async validateEvents<S>({
|
||||
events,
|
||||
newEvents,
|
||||
lastBlock,
|
||||
}: BaseEvents<MultiDepositsEvents | MultiWithdrawalsEvents> & {
|
||||
newEvents: (MultiDepositsEvents | MultiWithdrawalsEvents)[];
|
||||
}): Promise<S> {
|
||||
const tree = await super.validateEvents<S>({
|
||||
events,
|
||||
newEvents,
|
||||
lastBlock,
|
||||
});
|
||||
|
||||
if (this.merkleTreeService && this.treeCache) {
|
||||
const instancesWithNewEvents = [
|
||||
...new Set(
|
||||
newEvents.filter(({ event }) => event === 'Deposit').map(({ instanceAddress }) => instanceAddress),
|
||||
),
|
||||
];
|
||||
|
||||
for (const instance of instancesWithNewEvents) {
|
||||
const { amount, currency } = this.instances[instance];
|
||||
|
||||
// Only create cached tree for native currencies
|
||||
if (currency !== this.nativeCurrency) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const depositEvents = events.filter(
|
||||
({ instanceAddress, event }) => instanceAddress === instance && event === 'Deposit',
|
||||
) as MultiDepositsEvents[];
|
||||
|
||||
// Create tree cache with existing tree
|
||||
if (tree && this.merkleTreeService.Tornado.target === instance) {
|
||||
await this.treeCache.createTree({
|
||||
netId: this.netId,
|
||||
amount,
|
||||
currency,
|
||||
events: depositEvents,
|
||||
tree: tree as unknown as MerkleTree,
|
||||
});
|
||||
|
||||
// Create new tree cache
|
||||
} else {
|
||||
const merkleTreeService = new MerkleTreeService({
|
||||
netId: this.netId,
|
||||
amount,
|
||||
currency,
|
||||
Tornado: Tornado__factory.connect(instance, this.provider),
|
||||
merkleWorkerPath: this.merkleTreeService.merkleWorkerPath,
|
||||
});
|
||||
|
||||
const tree = await merkleTreeService.verifyTree(depositEvents);
|
||||
|
||||
await this.treeCache.createTree({
|
||||
netId: this.netId,
|
||||
amount,
|
||||
currency,
|
||||
events: depositEvents,
|
||||
tree,
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return tree;
|
||||
}
|
||||
|
||||
async saveEvents({
|
||||
events,
|
||||
newEvents,
|
||||
lastBlock,
|
||||
}: BaseEvents<MultiDepositsEvents | MultiWithdrawalsEvents> & {
|
||||
newEvents: (MultiDepositsEvents | MultiWithdrawalsEvents)[];
|
||||
}) {
|
||||
const instancesWithNewEvents = [...new Set(newEvents.map(({ instanceAddress }) => instanceAddress))];
|
||||
|
||||
for (const instance of instancesWithNewEvents) {
|
||||
const { currency, amount } = this.instances[instance];
|
||||
|
||||
const { depositEvents, withdrawalEvents } = events.reduce(
|
||||
(acc, curr) => {
|
||||
if (curr.instanceAddress === instance) {
|
||||
if (curr.event === 'Deposit') {
|
||||
acc.depositEvents.push({
|
||||
...(curr as MultiDepositsEvents),
|
||||
event: undefined,
|
||||
instanceAddress: undefined,
|
||||
} as DepositsEvents);
|
||||
} else if (curr.event === 'Withdrawal') {
|
||||
acc.withdrawalEvents.push({
|
||||
...(curr as MultiWithdrawalsEvents),
|
||||
event: undefined,
|
||||
instanceAddress: undefined,
|
||||
relayerAddress: undefined,
|
||||
} as WithdrawalsEvents);
|
||||
}
|
||||
}
|
||||
return acc;
|
||||
},
|
||||
{
|
||||
depositEvents: [] as DepositsEvents[],
|
||||
withdrawalEvents: [] as WithdrawalsEvents[],
|
||||
},
|
||||
);
|
||||
|
||||
await writeFile(
|
||||
path.join(this.userDirectory, `recent_deposits_${this.netId}_${currency}_${amount}.json`),
|
||||
JSON.stringify(depositEvents.slice(depositEvents.length - 10).reverse(), null, 2) + '\n',
|
||||
);
|
||||
|
||||
await saveUserFile({
|
||||
fileName: `deposits_${this.netId}_${currency}_${amount}.json`,
|
||||
userDirectory: this.userDirectory,
|
||||
dataString: JSON.stringify(depositEvents, null, 2) + '\n',
|
||||
lastBlock,
|
||||
});
|
||||
|
||||
await saveUserFile({
|
||||
fileName: `withdrawals_${this.netId}_${currency}_${amount}.json`,
|
||||
userDirectory: this.userDirectory,
|
||||
dataString: JSON.stringify(withdrawalEvents, null, 2) + '\n',
|
||||
lastBlock,
|
||||
});
|
||||
|
||||
console.log(
|
||||
`\nSaved ${this.netId}_${currency}_${amount}.json event: ` +
|
||||
`${depositEvents.length} deposits ${withdrawalEvents.length} withdrawals\n`,
|
||||
);
|
||||
}
|
||||
|
||||
await saveUserFile({
|
||||
fileName: this.getInstanceName() + '.json',
|
||||
userDirectory: this.userDirectory,
|
||||
dataString: JSON.stringify(events, null, 2) + '\n',
|
||||
lastBlock,
|
||||
});
|
||||
}
|
||||
|
||||
async updateEvents<S>() {
|
||||
const { events, lastBlock, validateResult } = await super.updateEvents<S>();
|
||||
|
||||
await saveLastBlock({
|
||||
fileName: this.getInstanceName(),
|
||||
userDirectory: this.userDirectory,
|
||||
lastBlock,
|
||||
});
|
||||
|
||||
return {
|
||||
events,
|
||||
lastBlock,
|
||||
validateResult,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
export interface NodeEchoServiceConstructor extends BaseEchoServiceConstructor {
|
||||
cacheDirectory: string;
|
||||
userDirectory: string;
|
||||
@ -368,6 +693,14 @@ export class NodeGovernanceService extends BaseGovernanceService {
|
||||
logger,
|
||||
getInstanceName: this.getInstanceName,
|
||||
});
|
||||
|
||||
this.batchTransactionService = new NodeTransactionsService({
|
||||
netId,
|
||||
provider,
|
||||
onProgress: this.updateTransactionProgress,
|
||||
logger,
|
||||
getInstanceName: this.getInstanceName,
|
||||
});
|
||||
}
|
||||
|
||||
updateEventProgress({ fromBlock, toBlock, count }: Parameters<BatchEventOnProgress>[0]) {
|
||||
@ -376,6 +709,12 @@ export class NodeGovernanceService extends BaseGovernanceService {
|
||||
}
|
||||
}
|
||||
|
||||
updateTransactionProgress({ currentIndex, totalIndex }: Parameters<BatchBlockOnProgress>[0]) {
|
||||
if (totalIndex) {
|
||||
this.logger.debug(`${this.getInstanceName()}: Fetched ${currentIndex} governance txs of ${totalIndex}`);
|
||||
}
|
||||
}
|
||||
|
||||
async getEventsFromDB() {
|
||||
return await loadSavedEvents<AllGovernanceEvents>({
|
||||
name: this.getInstanceName(),
|
||||
@ -599,6 +938,22 @@ export class NodeRevenueService extends BaseRevenueService {
|
||||
logger,
|
||||
getInstanceName: this.getInstanceName,
|
||||
});
|
||||
|
||||
this.batchTransactionService = new NodeTransactionsService({
|
||||
netId,
|
||||
provider,
|
||||
onProgress: this.updateTransactionProgress,
|
||||
logger,
|
||||
getInstanceName: this.getInstanceName,
|
||||
});
|
||||
|
||||
this.batchBlockService = new NodeBlocksService({
|
||||
netId,
|
||||
provider,
|
||||
onProgress: this.updateBlockProgress,
|
||||
logger,
|
||||
getInstanceName: this.getInstanceName,
|
||||
});
|
||||
}
|
||||
|
||||
updateEventProgress({ fromBlock, toBlock, count }: Parameters<BatchEventOnProgress>[0]) {
|
||||
@ -607,6 +962,18 @@ export class NodeRevenueService extends BaseRevenueService {
|
||||
}
|
||||
}
|
||||
|
||||
updateTransactionProgress({ currentIndex, totalIndex }: Parameters<BatchBlockOnProgress>[0]) {
|
||||
if (totalIndex) {
|
||||
this.logger.debug(`${this.getInstanceName()}: Fetched ${currentIndex} txs of ${totalIndex}`);
|
||||
}
|
||||
}
|
||||
|
||||
updateBlockProgress({ currentIndex, totalIndex }: Parameters<BatchBlockOnProgress>[0]) {
|
||||
if (totalIndex) {
|
||||
this.logger.debug(`${this.getInstanceName()}: Fetched ${currentIndex} blocks of ${totalIndex}`);
|
||||
}
|
||||
}
|
||||
|
||||
async getEventsFromDB() {
|
||||
return await loadSavedEvents<StakeBurnedEvents>({
|
||||
name: this.getInstanceName(),
|
||||
|
@ -7,8 +7,6 @@ import { fastifyCors } from '@fastify/cors';
|
||||
import {
|
||||
NetIdType,
|
||||
getConfig,
|
||||
DEPOSIT,
|
||||
WITHDRAWAL,
|
||||
DepositsEvents,
|
||||
WithdrawalsEvents,
|
||||
EchoEvents,
|
||||
@ -195,11 +193,16 @@ export async function handleEvents(router: Router, netId: NetIdType, req: Fastif
|
||||
} = router;
|
||||
const { type, currency, amount, fromBlock, recent } = req.body as unknown as TovarishEventsQuery;
|
||||
|
||||
const name = [DEPOSIT, WITHDRAWAL].includes(type) ? `${type}s_${netId}_${currency}_${amount}` : `${type}_${netId}`;
|
||||
const name = ['deposit', 'withdrawal'].includes(type)
|
||||
? `${type}s_${netId}_${currency}_${amount}`
|
||||
: `${type}_${netId}`;
|
||||
|
||||
// Can return 0 events but we just return error codes here
|
||||
// Return 0 length events if not exist (likely 0 events, can be checked by lastSyncBlock === fromBlock)
|
||||
if (!(await existsAsync(path.join(userDirectory, `${name}.json`)))) {
|
||||
reply.code(404).send(`Events ${name} not found!`);
|
||||
reply.send({
|
||||
events: [],
|
||||
lastSyncBlock: fromBlock,
|
||||
} as BaseTovarishEvents<AllTovarishEvents>);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -208,13 +211,24 @@ export async function handleEvents(router: Router, netId: NetIdType, req: Fastif
|
||||
}>(router, { type: 'status' });
|
||||
|
||||
const lastSyncBlock = Number(
|
||||
[DEPOSIT, WITHDRAWAL].includes(type)
|
||||
? syncManagerStatus.cachedEvents[netId]?.instances?.[String(currency)]?.[String(amount)]?.[
|
||||
`${type}s` as 'deposits' | 'withdrawals'
|
||||
]?.lastBlock
|
||||
['deposit', 'withdrawal'].includes(type)
|
||||
? syncManagerStatus.cachedEvents[netId]?.tornado?.lastBlock
|
||||
: syncManagerStatus.cachedEvents[netId]?.[String(type) as keyof TovarishEventsStatus]?.lastBlock,
|
||||
);
|
||||
|
||||
if (type === 'deposit' && recent) {
|
||||
const { events } = await loadSavedEvents<AllTovarishEvents>({
|
||||
name: 'recent_' + name,
|
||||
userDirectory,
|
||||
});
|
||||
|
||||
reply.send({
|
||||
events,
|
||||
lastSyncBlock,
|
||||
} as BaseTovarishEvents<AllTovarishEvents>);
|
||||
return;
|
||||
}
|
||||
|
||||
const { events } = await loadSavedEvents<AllTovarishEvents>({
|
||||
name,
|
||||
userDirectory,
|
||||
@ -222,12 +236,7 @@ export async function handleEvents(router: Router, netId: NetIdType, req: Fastif
|
||||
|
||||
if (recent) {
|
||||
reply.send({
|
||||
events: events.slice(-10).sort((a, b) => {
|
||||
if (a.blockNumber === b.blockNumber) {
|
||||
return b.logIndex - a.logIndex;
|
||||
}
|
||||
return b.blockNumber - a.blockNumber;
|
||||
}),
|
||||
events: events.slice(events.length - 10).reverse(),
|
||||
lastSyncBlock,
|
||||
} as BaseTovarishEvents<AllTovarishEvents>);
|
||||
return;
|
||||
|
@ -7,8 +7,6 @@ import {
|
||||
getInstanceByAddress,
|
||||
enabledChains,
|
||||
TovarishEventsQuery,
|
||||
WITHDRAWAL,
|
||||
DEPOSIT,
|
||||
addressSchemaType,
|
||||
proofSchemaType,
|
||||
bytes32SchemaType,
|
||||
@ -182,7 +180,7 @@ export function getEventsKeyword(netId: NetIdType) {
|
||||
try {
|
||||
const { type, currency, amount } = data;
|
||||
|
||||
if ([DEPOSIT, WITHDRAWAL].includes(type)) {
|
||||
if (['deposit', 'withdrawal'].includes(type)) {
|
||||
const instanceAddress = config.tokens[String(currency)]?.instanceAddress?.[String(amount)];
|
||||
|
||||
if (!instanceAddress) {
|
||||
@ -207,7 +205,7 @@ export function getEventsKeyword(netId: NetIdType) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return ['echo', 'encrypted_notes'].includes(type);
|
||||
return ['tornado', 'echo', 'encrypted_notes'].includes(type);
|
||||
} catch {
|
||||
return false;
|
||||
}
|
||||
|
@ -21,12 +21,10 @@ import {
|
||||
OffchainOracle__factory,
|
||||
TornadoFeeOracle,
|
||||
OvmGasPriceOracle__factory,
|
||||
getActiveTokens,
|
||||
TovarishEventsStatus,
|
||||
InstanceEventsStatus,
|
||||
TovarishSyncStatus,
|
||||
EventsStatus,
|
||||
ReverseRecords__factory,
|
||||
getMultiInstances,
|
||||
} from '@tornado/core';
|
||||
|
||||
import { RelayerConfig } from '../config';
|
||||
@ -38,23 +36,10 @@ import {
|
||||
NodeGovernanceService,
|
||||
NodeRegistryService,
|
||||
NodeRevenueService,
|
||||
NodeTornadoService,
|
||||
NodeMultiTornadoService,
|
||||
} from './events';
|
||||
import { ErrorTypes, ErrorMessages, newError } from './error';
|
||||
|
||||
export interface AmountsServices {
|
||||
depositsService: NodeTornadoService;
|
||||
withdrawalsService: NodeTornadoService;
|
||||
}
|
||||
|
||||
export interface CurrencyServices {
|
||||
[index: string]: AmountsServices;
|
||||
}
|
||||
|
||||
export interface TornadoServices {
|
||||
[index: string]: CurrencyServices;
|
||||
}
|
||||
|
||||
export interface Services {
|
||||
provider: Provider;
|
||||
tokenPriceOracle: TokenPriceOracle;
|
||||
@ -64,7 +49,7 @@ export interface Services {
|
||||
revenueService?: NodeRevenueService;
|
||||
echoService: NodeEchoService;
|
||||
encryptedNotesService: NodeEncryptedNotesService;
|
||||
tornadoServices: TornadoServices;
|
||||
tornadoServices: NodeMultiTornadoService;
|
||||
}
|
||||
|
||||
export interface CachedServices {
|
||||
@ -131,7 +116,6 @@ function setupServices(syncManager: SyncManager) {
|
||||
const provider = getProviderWithNetId(netId, rpcUrl, config);
|
||||
|
||||
const {
|
||||
tokens,
|
||||
nativeCurrency,
|
||||
routerContract,
|
||||
echoContract,
|
||||
@ -229,56 +213,31 @@ function setupServices(syncManager: SyncManager) {
|
||||
logger,
|
||||
});
|
||||
|
||||
services.tornadoServices = {} as TornadoServices;
|
||||
const instances = getMultiInstances(netId, config);
|
||||
|
||||
for (const currency of getActiveTokens(config)) {
|
||||
const currencyConfig = tokens[currency];
|
||||
const [firstInstance, { amount, currency }] = Object.entries(instances)[0];
|
||||
|
||||
const currencyService = (services.tornadoServices[currency] = {} as CurrencyServices);
|
||||
|
||||
for (const [amount, instanceAddress] of Object.entries(currencyConfig.instanceAddress)) {
|
||||
const Tornado = Tornado__factory.connect(instanceAddress, provider);
|
||||
|
||||
const amountService = (currencyService[amount] = {} as AmountsServices);
|
||||
|
||||
const TornadoServiceConstructor = {
|
||||
services.tornadoServices = new NodeMultiTornadoService({
|
||||
netId,
|
||||
provider,
|
||||
Tornado,
|
||||
amount,
|
||||
currency,
|
||||
instances,
|
||||
deployedBlock,
|
||||
cacheDirectory,
|
||||
userDirectory,
|
||||
nativeCurrency,
|
||||
logger,
|
||||
};
|
||||
|
||||
amountService.depositsService = new NodeTornadoService({
|
||||
...TornadoServiceConstructor,
|
||||
merkleTreeService: new MerkleTreeService({
|
||||
netId,
|
||||
amount,
|
||||
currency,
|
||||
Tornado,
|
||||
Tornado: Tornado__factory.connect(firstInstance, provider),
|
||||
merkleWorkerPath,
|
||||
}),
|
||||
treeCache: new TreeCache({
|
||||
netId,
|
||||
amount,
|
||||
currency,
|
||||
userDirectory: userTreeDir,
|
||||
}),
|
||||
optionalTree: true,
|
||||
type: 'Deposit',
|
||||
nativeCurrency,
|
||||
cacheDirectory,
|
||||
userDirectory,
|
||||
logger,
|
||||
});
|
||||
|
||||
amountService.withdrawalsService = new NodeTornadoService({
|
||||
...TornadoServiceConstructor,
|
||||
type: 'Withdrawal',
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
syncManager.cachedServices = cachedServices;
|
||||
@ -413,12 +372,11 @@ export async function syncNetworkEvents(syncManager: SyncManager, netId: NetIdTy
|
||||
|
||||
const eventsStatus = {
|
||||
governance: governanceService ? {} : undefined,
|
||||
registered: registryService ? {} : undefined,
|
||||
registry: registryService ? {} : undefined,
|
||||
revenue: revenueService ? {} : undefined,
|
||||
echo: {},
|
||||
encrypted_notes: {},
|
||||
instances: {},
|
||||
tornado: {},
|
||||
} as TovarishEventsStatus;
|
||||
|
||||
if (governanceService) {
|
||||
@ -447,12 +405,6 @@ export async function syncNetworkEvents(syncManager: SyncManager, netId: NetIdTy
|
||||
{
|
||||
const { lastBlock, timestamp, relayers } = await registryService.updateRelayers();
|
||||
|
||||
eventsStatus.registered = {
|
||||
lastBlock,
|
||||
timestamp,
|
||||
relayers: relayers.length,
|
||||
};
|
||||
|
||||
logger.info(
|
||||
`${netId}: Updated registry relayers (total: ${relayers.length}, block: ${lastBlock}, timestamp: ${timestamp})`,
|
||||
);
|
||||
@ -492,45 +444,17 @@ export async function syncNetworkEvents(syncManager: SyncManager, netId: NetIdTy
|
||||
`${netId}: Updated encrypted notes events (total: ${encryptedNotesEvents.events.length}, block: ${encryptedNotesEvents.lastBlock})`,
|
||||
);
|
||||
|
||||
const currencies = Object.keys(tornadoServices);
|
||||
const tornadoEvents = await tornadoServices.updateEvents();
|
||||
|
||||
for (const currency of currencies) {
|
||||
const currencyStatus = (eventsStatus.instances[currency] = {} as InstanceEventsStatus);
|
||||
|
||||
const amounts = Object.keys(tornadoServices[currency]);
|
||||
|
||||
for (const amount of amounts) {
|
||||
const instanceStatus = (currencyStatus[amount] = {
|
||||
deposits: {} as EventsStatus,
|
||||
withdrawals: {} as EventsStatus,
|
||||
});
|
||||
|
||||
const { depositsService, withdrawalsService } = tornadoServices[currency][amount];
|
||||
|
||||
const depositEvents = await depositsService.updateEvents();
|
||||
|
||||
instanceStatus.deposits = {
|
||||
events: depositEvents.events.length,
|
||||
lastBlock: depositEvents.lastBlock,
|
||||
eventsStatus.tornado = {
|
||||
events: tornadoEvents.events.length,
|
||||
lastBlock: tornadoEvents.lastBlock,
|
||||
};
|
||||
|
||||
logger.info(
|
||||
`${netId}: Updated ${currency} ${amount} Tornado deposit events (total: ${depositEvents.events.length}, block: ${depositEvents.lastBlock})`,
|
||||
`${netId}: Updated tornado events (total: ${tornadoEvents.events.length}, block: ${tornadoEvents.lastBlock})`,
|
||||
);
|
||||
|
||||
const withdrawalEvents = await withdrawalsService.updateEvents();
|
||||
|
||||
instanceStatus.withdrawals = {
|
||||
events: withdrawalEvents.events.length,
|
||||
lastBlock: withdrawalEvents.lastBlock,
|
||||
};
|
||||
|
||||
logger.info(
|
||||
`${netId}: Updated ${currency} ${amount} Tornado withdrawal events (total: ${withdrawalEvents.events.length}, block: ${withdrawalEvents.lastBlock})`,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
cachedEvents[netId] = eventsStatus;
|
||||
|
||||
syncStatus[netId].events = true;
|
||||
|
@ -10,9 +10,6 @@ import type { NetIdType } from '@tornado/core';
|
||||
import { saveUserFile } from './data';
|
||||
|
||||
export interface TreeCacheConstructor {
|
||||
netId: NetIdType;
|
||||
amount: string;
|
||||
currency: string;
|
||||
userDirectory: string;
|
||||
PARTS_COUNT?: number;
|
||||
LEAVES?: number;
|
||||
@ -29,30 +26,46 @@ export interface treeMetadata {
|
||||
}
|
||||
|
||||
export class TreeCache {
|
||||
netId: NetIdType;
|
||||
amount: string;
|
||||
currency: string;
|
||||
userDirectory: string;
|
||||
|
||||
PARTS_COUNT: number;
|
||||
|
||||
constructor({ netId, amount, currency, userDirectory, PARTS_COUNT = 4 }: TreeCacheConstructor) {
|
||||
this.netId = netId;
|
||||
this.amount = amount;
|
||||
this.currency = currency;
|
||||
constructor({ userDirectory, PARTS_COUNT = 4 }: TreeCacheConstructor) {
|
||||
this.userDirectory = userDirectory;
|
||||
|
||||
this.PARTS_COUNT = PARTS_COUNT;
|
||||
}
|
||||
|
||||
getInstanceName(): string {
|
||||
return `deposits_${this.netId}_${this.currency}_${this.amount}`;
|
||||
static getInstanceName({
|
||||
netId,
|
||||
amount,
|
||||
currency,
|
||||
}: {
|
||||
netId: NetIdType;
|
||||
amount: string;
|
||||
currency: string;
|
||||
}): string {
|
||||
return `deposits_${netId}_${currency}_${amount}`;
|
||||
}
|
||||
|
||||
async createTree(events: DepositsEvents[], tree: MerkleTree) {
|
||||
async createTree({
|
||||
netId,
|
||||
amount,
|
||||
currency,
|
||||
events,
|
||||
tree,
|
||||
}: {
|
||||
netId: NetIdType;
|
||||
amount: string;
|
||||
currency: string;
|
||||
events: DepositsEvents[];
|
||||
tree: MerkleTree;
|
||||
}) {
|
||||
const bloom = new BloomFilter(events.length);
|
||||
|
||||
console.log(`Creating cached tree for ${this.getInstanceName()}\n`);
|
||||
const instance = TreeCache.getInstanceName({ netId, amount, currency });
|
||||
|
||||
console.log(`Creating cached tree for ${instance}\n`);
|
||||
|
||||
// events indexed by commitment
|
||||
const eventsData = events.reduce(
|
||||
@ -90,7 +103,7 @@ export class TreeCache {
|
||||
2,
|
||||
) + '\n';
|
||||
|
||||
const fileName = `${this.getInstanceName()}_slice${index + 1}.json`;
|
||||
const fileName = `${instance}_slice${index + 1}.json`;
|
||||
|
||||
await saveUserFile({
|
||||
fileName,
|
||||
@ -102,7 +115,7 @@ export class TreeCache {
|
||||
|
||||
const dataString = bloom.serialize() + '\n';
|
||||
|
||||
const fileName = `${this.getInstanceName()}_bloom.json`;
|
||||
const fileName = `${instance}_bloom.json`;
|
||||
|
||||
await saveUserFile({
|
||||
fileName,
|
||||
|
BIN
static/events/tornado_1.json.zip
vendored
Normal file
BIN
static/events/tornado_1.json.zip
vendored
Normal file
Binary file not shown.
BIN
static/events/tornado_10.json.zip
vendored
Normal file
BIN
static/events/tornado_10.json.zip
vendored
Normal file
Binary file not shown.
BIN
static/events/tornado_100.json.zip
vendored
Normal file
BIN
static/events/tornado_100.json.zip
vendored
Normal file
Binary file not shown.
BIN
static/events/tornado_11155111.json.zip
vendored
Normal file
BIN
static/events/tornado_11155111.json.zip
vendored
Normal file
Binary file not shown.
BIN
static/events/tornado_137.json.zip
vendored
Normal file
BIN
static/events/tornado_137.json.zip
vendored
Normal file
Binary file not shown.
BIN
static/events/tornado_42161.json.zip
vendored
Normal file
BIN
static/events/tornado_42161.json.zip
vendored
Normal file
Binary file not shown.
BIN
static/events/tornado_43114.json.zip
vendored
Normal file
BIN
static/events/tornado_43114.json.zip
vendored
Normal file
Binary file not shown.
BIN
static/events/tornado_56.json.zip
vendored
Normal file
BIN
static/events/tornado_56.json.zip
vendored
Normal file
Binary file not shown.
@ -690,9 +690,9 @@
|
||||
"@openzeppelin/contracts-v3" "npm:@openzeppelin/contracts@3.2.0-rc.0"
|
||||
ethers "^6.13.4"
|
||||
|
||||
"@tornado/core@git+https://git.tornado.ws/tornadocontrib/tornado-core.git#94a62e6193c99457a8dfae0d8684bee299cb1097":
|
||||
"@tornado/core@git+https://git.tornado.ws/tornadocontrib/tornado-core.git#68fcf07c2a344a1f7f74895301f362aa059b53e2":
|
||||
version "1.0.19"
|
||||
resolved "git+https://git.tornado.ws/tornadocontrib/tornado-core.git#94a62e6193c99457a8dfae0d8684bee299cb1097"
|
||||
resolved "git+https://git.tornado.ws/tornadocontrib/tornado-core.git#68fcf07c2a344a1f7f74895301f362aa059b53e2"
|
||||
dependencies:
|
||||
"@ensdomains/content-hash" "2.5.7"
|
||||
"@metamask/eth-sig-util" "^8.0.0"
|
||||
|
Loading…
Reference in New Issue
Block a user