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'),
|
cacheDir: path_1.default.join(STATIC_DIR, './events'),
|
||||||
userEventsDir: path_1.default.join(USER_DIR, './events'),
|
userEventsDir: path_1.default.join(USER_DIR, './events'),
|
||||||
userTreeDir: path_1.default.join(USER_DIR, './trees'),
|
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 type { Logger } from 'winston';
|
||||||
import { TreeCache } from './treeCache';
|
import { TreeCache } from './treeCache';
|
||||||
export interface NodeEventsConstructor extends BatchEventServiceConstructor {
|
export interface NodeEventsConstructor extends BatchEventServiceConstructor {
|
||||||
@ -12,6 +12,23 @@ export declare class NodeEventsService extends BatchEventsService {
|
|||||||
getInstanceName: () => string;
|
getInstanceName: () => string;
|
||||||
constructor(serviceConstructor: NodeEventsConstructor);
|
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 {
|
export interface NodeTornadoServiceConstructor extends BaseTornadoServiceConstructor {
|
||||||
cacheDirectory: string;
|
cacheDirectory: string;
|
||||||
userDirectory: string;
|
userDirectory: string;
|
||||||
@ -27,10 +44,12 @@ export declare class NodeTornadoService extends BaseTornadoService {
|
|||||||
treeCache?: TreeCache;
|
treeCache?: TreeCache;
|
||||||
constructor(serviceConstructor: NodeTornadoServiceConstructor);
|
constructor(serviceConstructor: NodeTornadoServiceConstructor);
|
||||||
updateEventProgress({ fromBlock, toBlock, count }: Parameters<BatchEventOnProgress>[0]): void;
|
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>>;
|
getEventsFromDB(): Promise<BaseEvents<DepositsEvents | WithdrawalsEvents>>;
|
||||||
getEventsFromCache(): Promise<import("@tornado/core").CachedEvents<DepositsEvents | WithdrawalsEvents>>;
|
getEventsFromCache(): Promise<import("@tornado/core").CachedEvents<DepositsEvents | WithdrawalsEvents>>;
|
||||||
validateEvents<S>({ events, lastBlock, hasNewEvents, }: BaseEvents<DepositsEvents | WithdrawalsEvents> & {
|
validateEvents<S>({ events, newEvents, lastBlock, }: BaseEvents<DepositsEvents | WithdrawalsEvents> & {
|
||||||
hasNewEvents?: boolean;
|
newEvents: (DepositsEvents | WithdrawalsEvents)[];
|
||||||
}): Promise<S>;
|
}): Promise<S>;
|
||||||
saveEvents({ events, lastBlock }: BaseEvents<DepositsEvents | WithdrawalsEvents>): Promise<void>;
|
saveEvents({ events, lastBlock }: BaseEvents<DepositsEvents | WithdrawalsEvents>): Promise<void>;
|
||||||
updateEvents<S>(): Promise<{
|
updateEvents<S>(): Promise<{
|
||||||
@ -39,6 +58,37 @@ export declare class NodeTornadoService extends BaseTornadoService {
|
|||||||
validateResult: Awaited<S>;
|
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 {
|
export interface NodeEchoServiceConstructor extends BaseEchoServiceConstructor {
|
||||||
cacheDirectory: string;
|
cacheDirectory: string;
|
||||||
userDirectory: string;
|
userDirectory: string;
|
||||||
@ -90,6 +140,7 @@ export declare class NodeGovernanceService extends BaseGovernanceService {
|
|||||||
logger: Logger;
|
logger: Logger;
|
||||||
constructor(serviceConstructor: NodeGovernanceServiceConstructor);
|
constructor(serviceConstructor: NodeGovernanceServiceConstructor);
|
||||||
updateEventProgress({ fromBlock, toBlock, count }: Parameters<BatchEventOnProgress>[0]): void;
|
updateEventProgress({ fromBlock, toBlock, count }: Parameters<BatchEventOnProgress>[0]): void;
|
||||||
|
updateTransactionProgress({ currentIndex, totalIndex }: Parameters<BatchBlockOnProgress>[0]): void;
|
||||||
getEventsFromDB(): Promise<BaseEvents<AllGovernanceEvents>>;
|
getEventsFromDB(): Promise<BaseEvents<AllGovernanceEvents>>;
|
||||||
getEventsFromCache(): Promise<import("@tornado/core").CachedEvents<AllGovernanceEvents>>;
|
getEventsFromCache(): Promise<import("@tornado/core").CachedEvents<AllGovernanceEvents>>;
|
||||||
saveEvents({ events, lastBlock }: BaseEvents<AllGovernanceEvents>): Promise<void>;
|
saveEvents({ events, lastBlock }: BaseEvents<AllGovernanceEvents>): Promise<void>;
|
||||||
@ -133,6 +184,8 @@ export declare class NodeRevenueService extends BaseRevenueService {
|
|||||||
logger: Logger;
|
logger: Logger;
|
||||||
constructor(serviceConstructor: NodeRevenueServiceConstructor);
|
constructor(serviceConstructor: NodeRevenueServiceConstructor);
|
||||||
updateEventProgress({ fromBlock, toBlock, count }: Parameters<BatchEventOnProgress>[0]): void;
|
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>>;
|
getEventsFromDB(): Promise<BaseEvents<StakeBurnedEvents>>;
|
||||||
getEventsFromCache(): Promise<import("@tornado/core").CachedEvents<StakeBurnedEvents>>;
|
getEventsFromCache(): Promise<import("@tornado/core").CachedEvents<StakeBurnedEvents>>;
|
||||||
saveEvents({ events, lastBlock }: BaseEvents<StakeBurnedEvents>): Promise<void>;
|
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 };
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
||||||
};
|
};
|
||||||
Object.defineProperty(exports, "__esModule", { value: true });
|
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 path_1 = __importDefault(require("path"));
|
||||||
const promises_1 = require("fs/promises");
|
const promises_1 = require("fs/promises");
|
||||||
const core_1 = require("@tornado/core");
|
const core_1 = require("@tornado/core");
|
||||||
|
const contracts_1 = require("@tornado/contracts");
|
||||||
const data_1 = require("./data");
|
const data_1 = require("./data");
|
||||||
class NodeEventsService extends core_1.BatchEventsService {
|
class NodeEventsService extends core_1.BatchEventsService {
|
||||||
netId;
|
netId;
|
||||||
@ -20,6 +21,30 @@ class NodeEventsService extends core_1.BatchEventsService {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
exports.NodeEventsService = NodeEventsService;
|
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 {
|
class NodeTornadoService extends core_1.BaseTornadoService {
|
||||||
cacheDirectory;
|
cacheDirectory;
|
||||||
userDirectory;
|
userDirectory;
|
||||||
@ -41,6 +66,20 @@ class NodeTornadoService extends core_1.BaseTornadoService {
|
|||||||
logger,
|
logger,
|
||||||
getInstanceName: () => `${type.toLowerCase()}s_${netId}_${currency}_${amount}`,
|
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;
|
this.treeCache = treeCache;
|
||||||
}
|
}
|
||||||
updateEventProgress({ fromBlock, toBlock, count }) {
|
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}`);
|
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() {
|
async getEventsFromDB() {
|
||||||
return await (0, data_1.loadSavedEvents)({
|
return await (0, data_1.loadSavedEvents)({
|
||||||
name: this.getInstanceName(),
|
name: this.getInstanceName(),
|
||||||
@ -61,15 +110,21 @@ class NodeTornadoService extends core_1.BaseTornadoService {
|
|||||||
deployedBlock: this.deployedBlock,
|
deployedBlock: this.deployedBlock,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
async validateEvents({ events, lastBlock, hasNewEvents, }) {
|
async validateEvents({ events, newEvents, lastBlock, }) {
|
||||||
const tree = await super.validateEvents({
|
const tree = await super.validateEvents({
|
||||||
events,
|
events,
|
||||||
|
newEvents,
|
||||||
lastBlock,
|
lastBlock,
|
||||||
hasNewEvents,
|
|
||||||
});
|
});
|
||||||
if (tree && this.currency === this.nativeCurrency && this.treeCache) {
|
if (tree && this.currency === this.nativeCurrency && this.treeCache) {
|
||||||
const merkleTree = tree;
|
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`);
|
console.log(`${this.getInstanceName()}: Updated tree cache with root ${(0, core_1.toFixedHex)(BigInt(merkleTree.root))}\n`);
|
||||||
}
|
}
|
||||||
return tree;
|
return tree;
|
||||||
@ -97,6 +152,186 @@ class NodeTornadoService extends core_1.BaseTornadoService {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
exports.NodeTornadoService = NodeTornadoService;
|
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 {
|
class NodeEchoService extends core_1.BaseEchoService {
|
||||||
cacheDirectory;
|
cacheDirectory;
|
||||||
userDirectory;
|
userDirectory;
|
||||||
@ -237,12 +472,24 @@ class NodeGovernanceService extends core_1.BaseGovernanceService {
|
|||||||
logger,
|
logger,
|
||||||
getInstanceName: this.getInstanceName,
|
getInstanceName: this.getInstanceName,
|
||||||
});
|
});
|
||||||
|
this.batchTransactionService = new NodeTransactionsService({
|
||||||
|
netId,
|
||||||
|
provider,
|
||||||
|
onProgress: this.updateTransactionProgress,
|
||||||
|
logger,
|
||||||
|
getInstanceName: this.getInstanceName,
|
||||||
|
});
|
||||||
}
|
}
|
||||||
updateEventProgress({ fromBlock, toBlock, count }) {
|
updateEventProgress({ fromBlock, toBlock, count }) {
|
||||||
if (toBlock) {
|
if (toBlock) {
|
||||||
this.logger.debug(`${this.getInstanceName()}: Fetched ${count} events from ${fromBlock} to ${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() {
|
async getEventsFromDB() {
|
||||||
return await (0, data_1.loadSavedEvents)({
|
return await (0, data_1.loadSavedEvents)({
|
||||||
name: this.getInstanceName(),
|
name: this.getInstanceName(),
|
||||||
@ -423,12 +670,36 @@ class NodeRevenueService extends core_1.BaseRevenueService {
|
|||||||
logger,
|
logger,
|
||||||
getInstanceName: this.getInstanceName,
|
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 }) {
|
updateEventProgress({ fromBlock, toBlock, count }) {
|
||||||
if (toBlock) {
|
if (toBlock) {
|
||||||
this.logger.debug(`${this.getInstanceName()}: Fetched ${count} events from ${fromBlock} to ${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() {
|
async getEventsFromDB() {
|
||||||
return await (0, data_1.loadSavedEvents)({
|
return await (0, data_1.loadSavedEvents)({
|
||||||
name: this.getInstanceName(),
|
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) {
|
async function handleEvents(router, netId, req, reply) {
|
||||||
const { relayerConfig: { userEventsDir: userDirectory }, } = router;
|
const { relayerConfig: { userEventsDir: userDirectory }, } = router;
|
||||||
const { type, currency, amount, fromBlock, recent } = req.body;
|
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}`;
|
const name = ['deposit', 'withdrawal'].includes(type)
|
||||||
// Can return 0 events but we just return error codes here
|
? `${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`)))) {
|
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;
|
return;
|
||||||
}
|
}
|
||||||
const { syncManagerStatus } = await (0, routerMsg_1.sendMessage)(router, { type: 'status' });
|
const { syncManagerStatus } = await (0, routerMsg_1.sendMessage)(router, { type: 'status' });
|
||||||
const lastSyncBlock = Number([core_1.DEPOSIT, core_1.WITHDRAWAL].includes(type)
|
const lastSyncBlock = Number(['deposit', 'withdrawal'].includes(type)
|
||||||
? syncManagerStatus.cachedEvents[netId]?.instances?.[String(currency)]?.[String(amount)]?.[`${type}s`]?.lastBlock
|
? syncManagerStatus.cachedEvents[netId]?.tornado?.lastBlock
|
||||||
: syncManagerStatus.cachedEvents[netId]?.[String(type)]?.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)({
|
const { events } = await (0, data_1.loadSavedEvents)({
|
||||||
name,
|
name,
|
||||||
userDirectory,
|
userDirectory,
|
||||||
});
|
});
|
||||||
if (recent) {
|
if (recent) {
|
||||||
reply.send({
|
reply.send({
|
||||||
events: events.slice(-10).sort((a, b) => {
|
events: events.slice(events.length - 10).reverse(),
|
||||||
if (a.blockNumber === b.blockNumber) {
|
|
||||||
return b.logIndex - a.logIndex;
|
|
||||||
}
|
|
||||||
return b.blockNumber - a.blockNumber;
|
|
||||||
}),
|
|
||||||
lastSyncBlock,
|
lastSyncBlock,
|
||||||
});
|
});
|
||||||
return;
|
return;
|
||||||
|
4
lib/services/schema.js
vendored
4
lib/services/schema.js
vendored
@ -139,7 +139,7 @@ function getEventsKeyword(netId) {
|
|||||||
validate: (schema, data) => {
|
validate: (schema, data) => {
|
||||||
try {
|
try {
|
||||||
const { type, currency, amount } = data;
|
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)];
|
const instanceAddress = config.tokens[String(currency)]?.instanceAddress?.[String(amount)];
|
||||||
if (!instanceAddress) {
|
if (!instanceAddress) {
|
||||||
return false;
|
return false;
|
||||||
@ -159,7 +159,7 @@ function getEventsKeyword(netId) {
|
|||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return ['echo', 'encrypted_notes'].includes(type);
|
return ['tornado', 'echo', 'encrypted_notes'].includes(type);
|
||||||
}
|
}
|
||||||
catch {
|
catch {
|
||||||
return false;
|
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 type { Logger } from 'winston';
|
||||||
import { NetIdType, TokenPriceOracle, TornadoFeeOracle, TovarishEventsStatus, TovarishSyncStatus } from '@tornado/core';
|
import { NetIdType, TokenPriceOracle, TornadoFeeOracle, TovarishEventsStatus, TovarishSyncStatus } from '@tornado/core';
|
||||||
import { RelayerConfig } from '../config';
|
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';
|
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 {
|
export interface Services {
|
||||||
provider: Provider;
|
provider: Provider;
|
||||||
tokenPriceOracle: TokenPriceOracle;
|
tokenPriceOracle: TokenPriceOracle;
|
||||||
@ -23,7 +13,7 @@ export interface Services {
|
|||||||
revenueService?: NodeRevenueService;
|
revenueService?: NodeRevenueService;
|
||||||
echoService: NodeEchoService;
|
echoService: NodeEchoService;
|
||||||
encryptedNotesService: NodeEncryptedNotesService;
|
encryptedNotesService: NodeEncryptedNotesService;
|
||||||
tornadoServices: TornadoServices;
|
tornadoServices: NodeMultiTornadoService;
|
||||||
}
|
}
|
||||||
export interface CachedServices {
|
export interface CachedServices {
|
||||||
[index: NetIdType]: Services;
|
[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 config = (0, core_1.getConfig)(netId);
|
||||||
const rpcUrl = relayerConfig.rpcUrls[netId];
|
const rpcUrl = relayerConfig.rpcUrls[netId];
|
||||||
const provider = (0, core_1.getProviderWithNetId)(netId, rpcUrl, config);
|
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]) {
|
if (!syncStatus[netId]) {
|
||||||
syncStatus[netId] = {
|
syncStatus[netId] = {
|
||||||
events: false,
|
events: false,
|
||||||
@ -85,49 +85,29 @@ function setupServices(syncManager) {
|
|||||||
userDirectory,
|
userDirectory,
|
||||||
logger,
|
logger,
|
||||||
});
|
});
|
||||||
services.tornadoServices = {};
|
const instances = (0, core_1.getMultiInstances)(netId, config);
|
||||||
for (const currency of (0, core_1.getActiveTokens)(config)) {
|
const [firstInstance, { amount, currency }] = Object.entries(instances)[0];
|
||||||
const currencyConfig = tokens[currency];
|
services.tornadoServices = new events_1.NodeMultiTornadoService({
|
||||||
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 = {
|
|
||||||
netId,
|
netId,
|
||||||
provider,
|
provider,
|
||||||
Tornado,
|
instances,
|
||||||
amount,
|
|
||||||
currency,
|
|
||||||
deployedBlock,
|
deployedBlock,
|
||||||
cacheDirectory,
|
|
||||||
userDirectory,
|
|
||||||
nativeCurrency,
|
|
||||||
logger,
|
|
||||||
};
|
|
||||||
amountService.depositsService = new events_1.NodeTornadoService({
|
|
||||||
...TornadoServiceConstructor,
|
|
||||||
merkleTreeService: new core_1.MerkleTreeService({
|
merkleTreeService: new core_1.MerkleTreeService({
|
||||||
netId,
|
netId,
|
||||||
amount,
|
amount,
|
||||||
currency,
|
currency,
|
||||||
Tornado,
|
Tornado: contracts_1.Tornado__factory.connect(firstInstance, provider),
|
||||||
merkleWorkerPath,
|
merkleWorkerPath,
|
||||||
}),
|
}),
|
||||||
treeCache: new treeCache_1.TreeCache({
|
treeCache: new treeCache_1.TreeCache({
|
||||||
netId,
|
|
||||||
amount,
|
|
||||||
currency,
|
|
||||||
userDirectory: userTreeDir,
|
userDirectory: userTreeDir,
|
||||||
}),
|
}),
|
||||||
optionalTree: true,
|
optionalTree: true,
|
||||||
type: 'Deposit',
|
nativeCurrency,
|
||||||
|
cacheDirectory,
|
||||||
|
userDirectory,
|
||||||
|
logger,
|
||||||
});
|
});
|
||||||
amountService.withdrawalsService = new events_1.NodeTornadoService({
|
|
||||||
...TornadoServiceConstructor,
|
|
||||||
type: 'Withdrawal',
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
syncManager.cachedServices = cachedServices;
|
syncManager.cachedServices = cachedServices;
|
||||||
}
|
}
|
||||||
@ -215,12 +195,11 @@ async function syncNetworkEvents(syncManager, netId) {
|
|||||||
logger.info(`${netId}: Syncing events from block ${await provider.getBlockNumber()}`);
|
logger.info(`${netId}: Syncing events from block ${await provider.getBlockNumber()}`);
|
||||||
const eventsStatus = {
|
const eventsStatus = {
|
||||||
governance: governanceService ? {} : undefined,
|
governance: governanceService ? {} : undefined,
|
||||||
registered: registryService ? {} : undefined,
|
|
||||||
registry: registryService ? {} : undefined,
|
registry: registryService ? {} : undefined,
|
||||||
revenue: revenueService ? {} : undefined,
|
revenue: revenueService ? {} : undefined,
|
||||||
echo: {},
|
echo: {},
|
||||||
encrypted_notes: {},
|
encrypted_notes: {},
|
||||||
instances: {},
|
tornado: {},
|
||||||
};
|
};
|
||||||
if (governanceService) {
|
if (governanceService) {
|
||||||
const { events, lastBlock } = await governanceService.updateEvents();
|
const { events, lastBlock } = await governanceService.updateEvents();
|
||||||
@ -241,11 +220,6 @@ async function syncNetworkEvents(syncManager, netId) {
|
|||||||
}
|
}
|
||||||
{
|
{
|
||||||
const { lastBlock, timestamp, relayers } = await registryService.updateRelayers();
|
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})`);
|
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,
|
lastBlock: encryptedNotesEvents.lastBlock,
|
||||||
};
|
};
|
||||||
logger.info(`${netId}: Updated encrypted notes events (total: ${encryptedNotesEvents.events.length}, block: ${encryptedNotesEvents.lastBlock})`);
|
logger.info(`${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) {
|
eventsStatus.tornado = {
|
||||||
const currencyStatus = (eventsStatus.instances[currency] = {});
|
events: tornadoEvents.events.length,
|
||||||
const amounts = Object.keys(tornadoServices[currency]);
|
lastBlock: tornadoEvents.lastBlock,
|
||||||
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,
|
|
||||||
};
|
};
|
||||||
logger.info(`${netId}: Updated ${currency} ${amount} Tornado deposit events (total: ${depositEvents.events.length}, block: ${depositEvents.lastBlock})`);
|
logger.info(`${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;
|
cachedEvents[netId] = eventsStatus;
|
||||||
syncStatus[netId].events = true;
|
syncStatus[netId].events = true;
|
||||||
logger.info(`${netId}: Synced all events`);
|
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 { DepositsEvents } from '@tornado/core';
|
||||||
import type { NetIdType } from '@tornado/core';
|
import type { NetIdType } from '@tornado/core';
|
||||||
export interface TreeCacheConstructor {
|
export interface TreeCacheConstructor {
|
||||||
netId: NetIdType;
|
|
||||||
amount: string;
|
|
||||||
currency: string;
|
|
||||||
userDirectory: string;
|
userDirectory: string;
|
||||||
PARTS_COUNT?: number;
|
PARTS_COUNT?: number;
|
||||||
LEAVES?: number;
|
LEAVES?: number;
|
||||||
@ -24,12 +21,19 @@ export interface treeMetadata {
|
|||||||
leafIndex: number;
|
leafIndex: number;
|
||||||
}
|
}
|
||||||
export declare class TreeCache {
|
export declare class TreeCache {
|
||||||
|
userDirectory: string;
|
||||||
|
PARTS_COUNT: number;
|
||||||
|
constructor({ userDirectory, PARTS_COUNT }: TreeCacheConstructor);
|
||||||
|
static getInstanceName({ netId, amount, currency, }: {
|
||||||
netId: NetIdType;
|
netId: NetIdType;
|
||||||
amount: string;
|
amount: string;
|
||||||
currency: string;
|
currency: string;
|
||||||
userDirectory: string;
|
}): string;
|
||||||
PARTS_COUNT: number;
|
createTree({ netId, amount, currency, events, tree, }: {
|
||||||
constructor({ netId, amount, currency, userDirectory, PARTS_COUNT }: TreeCacheConstructor);
|
netId: NetIdType;
|
||||||
getInstanceName(): string;
|
amount: string;
|
||||||
createTree(events: DepositsEvents[], tree: MerkleTree): Promise<void>;
|
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 bloomfilter_js_1 = __importDefault(require("bloomfilter.js"));
|
||||||
const data_1 = require("./data");
|
const data_1 = require("./data");
|
||||||
class TreeCache {
|
class TreeCache {
|
||||||
netId;
|
|
||||||
amount;
|
|
||||||
currency;
|
|
||||||
userDirectory;
|
userDirectory;
|
||||||
PARTS_COUNT;
|
PARTS_COUNT;
|
||||||
constructor({ netId, amount, currency, userDirectory, PARTS_COUNT = 4 }) {
|
constructor({ userDirectory, PARTS_COUNT = 4 }) {
|
||||||
this.netId = netId;
|
|
||||||
this.amount = amount;
|
|
||||||
this.currency = currency;
|
|
||||||
this.userDirectory = userDirectory;
|
this.userDirectory = userDirectory;
|
||||||
this.PARTS_COUNT = PARTS_COUNT;
|
this.PARTS_COUNT = PARTS_COUNT;
|
||||||
}
|
}
|
||||||
getInstanceName() {
|
static getInstanceName({ netId, amount, currency, }) {
|
||||||
return `deposits_${this.netId}_${this.currency}_${this.amount}`;
|
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);
|
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
|
// events indexed by commitment
|
||||||
const eventsData = events.reduce((acc, { leafIndex, commitment, ...rest }, i) => {
|
const eventsData = events.reduce((acc, { leafIndex, commitment, ...rest }, i) => {
|
||||||
if (leafIndex !== i) {
|
if (leafIndex !== i) {
|
||||||
@ -46,7 +41,7 @@ class TreeCache {
|
|||||||
...slice,
|
...slice,
|
||||||
metadata,
|
metadata,
|
||||||
}, null, 2) + '\n';
|
}, null, 2) + '\n';
|
||||||
const fileName = `${this.getInstanceName()}_slice${index + 1}.json`;
|
const fileName = `${instance}_slice${index + 1}.json`;
|
||||||
await (0, data_1.saveUserFile)({
|
await (0, data_1.saveUserFile)({
|
||||||
fileName,
|
fileName,
|
||||||
userDirectory: this.userDirectory,
|
userDirectory: this.userDirectory,
|
||||||
@ -54,7 +49,7 @@ class TreeCache {
|
|||||||
});
|
});
|
||||||
}));
|
}));
|
||||||
const dataString = bloom.serialize() + '\n';
|
const dataString = bloom.serialize() + '\n';
|
||||||
const fileName = `${this.getInstanceName()}_bloom.json`;
|
const fileName = `${instance}_bloom.json`;
|
||||||
await (0, data_1.saveUserFile)({
|
await (0, data_1.saveUserFile)({
|
||||||
fileName,
|
fileName,
|
||||||
userDirectory: this.userDirectory,
|
userDirectory: this.userDirectory,
|
||||||
|
@ -14,7 +14,7 @@
|
|||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@fastify/cors": "^10.0.1",
|
"@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",
|
"bloomfilter.js": "^1.0.2",
|
||||||
"dotenv": "^16.4.5",
|
"dotenv": "^16.4.5",
|
||||||
"fastify": "^5.0.0",
|
"fastify": "^5.0.0",
|
||||||
|
@ -98,6 +98,6 @@ export function getRelayerConfig(): RelayerConfig {
|
|||||||
cacheDir: path.join(STATIC_DIR, './events'),
|
cacheDir: path.join(STATIC_DIR, './events'),
|
||||||
userEventsDir: path.join(USER_DIR, './events'),
|
userEventsDir: path.join(USER_DIR, './events'),
|
||||||
userTreeDir: path.join(USER_DIR, './trees'),
|
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 path from 'path';
|
||||||
import { readFile } from 'fs/promises';
|
import { readFile, writeFile } from 'fs/promises';
|
||||||
import {
|
import {
|
||||||
BaseTornadoService,
|
BaseTornadoService,
|
||||||
|
BaseMultiTornadoService,
|
||||||
BaseEncryptedNotesService,
|
BaseEncryptedNotesService,
|
||||||
BaseGovernanceService,
|
BaseGovernanceService,
|
||||||
BaseRegistryService,
|
BaseRegistryService,
|
||||||
BaseTornadoServiceConstructor,
|
BaseTornadoServiceConstructor,
|
||||||
|
BaseMultiTornadoServiceConstructor,
|
||||||
BaseEncryptedNotesServiceConstructor,
|
BaseEncryptedNotesServiceConstructor,
|
||||||
BaseGovernanceServiceConstructor,
|
BaseGovernanceServiceConstructor,
|
||||||
BaseRegistryServiceConstructor,
|
BaseRegistryServiceConstructor,
|
||||||
@ -17,6 +19,9 @@ import {
|
|||||||
BaseEvents,
|
BaseEvents,
|
||||||
DepositsEvents,
|
DepositsEvents,
|
||||||
WithdrawalsEvents,
|
WithdrawalsEvents,
|
||||||
|
MultiDepositsEvents,
|
||||||
|
MultiWithdrawalsEvents,
|
||||||
|
MerkleTreeService,
|
||||||
EncryptedNotesEvents,
|
EncryptedNotesEvents,
|
||||||
AllGovernanceEvents,
|
AllGovernanceEvents,
|
||||||
EchoEvents,
|
EchoEvents,
|
||||||
@ -27,7 +32,12 @@ import {
|
|||||||
BaseRevenueService,
|
BaseRevenueService,
|
||||||
BaseRevenueServiceConstructor,
|
BaseRevenueServiceConstructor,
|
||||||
StakeBurnedEvents,
|
StakeBurnedEvents,
|
||||||
|
BatchBlockOnProgress,
|
||||||
|
BatchBlockServiceConstructor,
|
||||||
|
BatchBlockService,
|
||||||
|
BatchTransactionService,
|
||||||
} from '@tornado/core';
|
} from '@tornado/core';
|
||||||
|
import { Tornado__factory } from '@tornado/contracts';
|
||||||
import type { MerkleTree } from '@tornado/fixed-merkle-tree';
|
import type { MerkleTree } from '@tornado/fixed-merkle-tree';
|
||||||
import type { Logger } from 'winston';
|
import type { Logger } from 'winston';
|
||||||
import { saveUserFile, loadSavedEvents, loadCachedEvents, existsAsync, saveLastBlock } from './data';
|
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 {
|
export interface NodeTornadoServiceConstructor extends BaseTornadoServiceConstructor {
|
||||||
cacheDirectory: string;
|
cacheDirectory: string;
|
||||||
userDirectory: string;
|
userDirectory: string;
|
||||||
@ -102,6 +146,22 @@ export class NodeTornadoService extends BaseTornadoService {
|
|||||||
getInstanceName: () => `${type.toLowerCase()}s_${netId}_${currency}_${amount}`,
|
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;
|
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() {
|
async getEventsFromDB() {
|
||||||
return await loadSavedEvents<DepositsEvents | WithdrawalsEvents>({
|
return await loadSavedEvents<DepositsEvents | WithdrawalsEvents>({
|
||||||
name: this.getInstanceName(),
|
name: this.getInstanceName(),
|
||||||
@ -128,21 +200,27 @@ export class NodeTornadoService extends BaseTornadoService {
|
|||||||
|
|
||||||
async validateEvents<S>({
|
async validateEvents<S>({
|
||||||
events,
|
events,
|
||||||
|
newEvents,
|
||||||
lastBlock,
|
lastBlock,
|
||||||
hasNewEvents,
|
|
||||||
}: BaseEvents<DepositsEvents | WithdrawalsEvents> & {
|
}: BaseEvents<DepositsEvents | WithdrawalsEvents> & {
|
||||||
hasNewEvents?: boolean;
|
newEvents: (DepositsEvents | WithdrawalsEvents)[];
|
||||||
}): Promise<S> {
|
}): Promise<S> {
|
||||||
const tree = await super.validateEvents<S>({
|
const tree = await super.validateEvents<S>({
|
||||||
events,
|
events,
|
||||||
|
newEvents,
|
||||||
lastBlock,
|
lastBlock,
|
||||||
hasNewEvents,
|
|
||||||
});
|
});
|
||||||
|
|
||||||
if (tree && this.currency === this.nativeCurrency && this.treeCache) {
|
if (tree && this.currency === this.nativeCurrency && this.treeCache) {
|
||||||
const merkleTree = tree as unknown as MerkleTree;
|
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(
|
console.log(
|
||||||
`${this.getInstanceName()}: Updated tree cache with root ${toFixedHex(BigInt(merkleTree.root))}\n`,
|
`${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 {
|
export interface NodeEchoServiceConstructor extends BaseEchoServiceConstructor {
|
||||||
cacheDirectory: string;
|
cacheDirectory: string;
|
||||||
userDirectory: string;
|
userDirectory: string;
|
||||||
@ -368,6 +693,14 @@ export class NodeGovernanceService extends BaseGovernanceService {
|
|||||||
logger,
|
logger,
|
||||||
getInstanceName: this.getInstanceName,
|
getInstanceName: this.getInstanceName,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
this.batchTransactionService = new NodeTransactionsService({
|
||||||
|
netId,
|
||||||
|
provider,
|
||||||
|
onProgress: this.updateTransactionProgress,
|
||||||
|
logger,
|
||||||
|
getInstanceName: this.getInstanceName,
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
updateEventProgress({ fromBlock, toBlock, count }: Parameters<BatchEventOnProgress>[0]) {
|
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() {
|
async getEventsFromDB() {
|
||||||
return await loadSavedEvents<AllGovernanceEvents>({
|
return await loadSavedEvents<AllGovernanceEvents>({
|
||||||
name: this.getInstanceName(),
|
name: this.getInstanceName(),
|
||||||
@ -599,6 +938,22 @@ export class NodeRevenueService extends BaseRevenueService {
|
|||||||
logger,
|
logger,
|
||||||
getInstanceName: this.getInstanceName,
|
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]) {
|
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() {
|
async getEventsFromDB() {
|
||||||
return await loadSavedEvents<StakeBurnedEvents>({
|
return await loadSavedEvents<StakeBurnedEvents>({
|
||||||
name: this.getInstanceName(),
|
name: this.getInstanceName(),
|
||||||
|
@ -7,8 +7,6 @@ import { fastifyCors } from '@fastify/cors';
|
|||||||
import {
|
import {
|
||||||
NetIdType,
|
NetIdType,
|
||||||
getConfig,
|
getConfig,
|
||||||
DEPOSIT,
|
|
||||||
WITHDRAWAL,
|
|
||||||
DepositsEvents,
|
DepositsEvents,
|
||||||
WithdrawalsEvents,
|
WithdrawalsEvents,
|
||||||
EchoEvents,
|
EchoEvents,
|
||||||
@ -195,11 +193,16 @@ export async function handleEvents(router: Router, netId: NetIdType, req: Fastif
|
|||||||
} = router;
|
} = router;
|
||||||
const { type, currency, amount, fromBlock, recent } = req.body as unknown as TovarishEventsQuery;
|
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`)))) {
|
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;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -208,13 +211,24 @@ export async function handleEvents(router: Router, netId: NetIdType, req: Fastif
|
|||||||
}>(router, { type: 'status' });
|
}>(router, { type: 'status' });
|
||||||
|
|
||||||
const lastSyncBlock = Number(
|
const lastSyncBlock = Number(
|
||||||
[DEPOSIT, WITHDRAWAL].includes(type)
|
['deposit', 'withdrawal'].includes(type)
|
||||||
? syncManagerStatus.cachedEvents[netId]?.instances?.[String(currency)]?.[String(amount)]?.[
|
? syncManagerStatus.cachedEvents[netId]?.tornado?.lastBlock
|
||||||
`${type}s` as 'deposits' | 'withdrawals'
|
|
||||||
]?.lastBlock
|
|
||||||
: syncManagerStatus.cachedEvents[netId]?.[String(type) as keyof TovarishEventsStatus]?.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>({
|
const { events } = await loadSavedEvents<AllTovarishEvents>({
|
||||||
name,
|
name,
|
||||||
userDirectory,
|
userDirectory,
|
||||||
@ -222,12 +236,7 @@ export async function handleEvents(router: Router, netId: NetIdType, req: Fastif
|
|||||||
|
|
||||||
if (recent) {
|
if (recent) {
|
||||||
reply.send({
|
reply.send({
|
||||||
events: events.slice(-10).sort((a, b) => {
|
events: events.slice(events.length - 10).reverse(),
|
||||||
if (a.blockNumber === b.blockNumber) {
|
|
||||||
return b.logIndex - a.logIndex;
|
|
||||||
}
|
|
||||||
return b.blockNumber - a.blockNumber;
|
|
||||||
}),
|
|
||||||
lastSyncBlock,
|
lastSyncBlock,
|
||||||
} as BaseTovarishEvents<AllTovarishEvents>);
|
} as BaseTovarishEvents<AllTovarishEvents>);
|
||||||
return;
|
return;
|
||||||
|
@ -7,8 +7,6 @@ import {
|
|||||||
getInstanceByAddress,
|
getInstanceByAddress,
|
||||||
enabledChains,
|
enabledChains,
|
||||||
TovarishEventsQuery,
|
TovarishEventsQuery,
|
||||||
WITHDRAWAL,
|
|
||||||
DEPOSIT,
|
|
||||||
addressSchemaType,
|
addressSchemaType,
|
||||||
proofSchemaType,
|
proofSchemaType,
|
||||||
bytes32SchemaType,
|
bytes32SchemaType,
|
||||||
@ -182,7 +180,7 @@ export function getEventsKeyword(netId: NetIdType) {
|
|||||||
try {
|
try {
|
||||||
const { type, currency, amount } = data;
|
const { type, currency, amount } = data;
|
||||||
|
|
||||||
if ([DEPOSIT, WITHDRAWAL].includes(type)) {
|
if (['deposit', 'withdrawal'].includes(type)) {
|
||||||
const instanceAddress = config.tokens[String(currency)]?.instanceAddress?.[String(amount)];
|
const instanceAddress = config.tokens[String(currency)]?.instanceAddress?.[String(amount)];
|
||||||
|
|
||||||
if (!instanceAddress) {
|
if (!instanceAddress) {
|
||||||
@ -207,7 +205,7 @@ export function getEventsKeyword(netId: NetIdType) {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
return ['echo', 'encrypted_notes'].includes(type);
|
return ['tornado', 'echo', 'encrypted_notes'].includes(type);
|
||||||
} catch {
|
} catch {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -21,12 +21,10 @@ import {
|
|||||||
OffchainOracle__factory,
|
OffchainOracle__factory,
|
||||||
TornadoFeeOracle,
|
TornadoFeeOracle,
|
||||||
OvmGasPriceOracle__factory,
|
OvmGasPriceOracle__factory,
|
||||||
getActiveTokens,
|
|
||||||
TovarishEventsStatus,
|
TovarishEventsStatus,
|
||||||
InstanceEventsStatus,
|
|
||||||
TovarishSyncStatus,
|
TovarishSyncStatus,
|
||||||
EventsStatus,
|
|
||||||
ReverseRecords__factory,
|
ReverseRecords__factory,
|
||||||
|
getMultiInstances,
|
||||||
} from '@tornado/core';
|
} from '@tornado/core';
|
||||||
|
|
||||||
import { RelayerConfig } from '../config';
|
import { RelayerConfig } from '../config';
|
||||||
@ -38,23 +36,10 @@ import {
|
|||||||
NodeGovernanceService,
|
NodeGovernanceService,
|
||||||
NodeRegistryService,
|
NodeRegistryService,
|
||||||
NodeRevenueService,
|
NodeRevenueService,
|
||||||
NodeTornadoService,
|
NodeMultiTornadoService,
|
||||||
} from './events';
|
} from './events';
|
||||||
import { ErrorTypes, ErrorMessages, newError } from './error';
|
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 {
|
export interface Services {
|
||||||
provider: Provider;
|
provider: Provider;
|
||||||
tokenPriceOracle: TokenPriceOracle;
|
tokenPriceOracle: TokenPriceOracle;
|
||||||
@ -64,7 +49,7 @@ export interface Services {
|
|||||||
revenueService?: NodeRevenueService;
|
revenueService?: NodeRevenueService;
|
||||||
echoService: NodeEchoService;
|
echoService: NodeEchoService;
|
||||||
encryptedNotesService: NodeEncryptedNotesService;
|
encryptedNotesService: NodeEncryptedNotesService;
|
||||||
tornadoServices: TornadoServices;
|
tornadoServices: NodeMultiTornadoService;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface CachedServices {
|
export interface CachedServices {
|
||||||
@ -131,7 +116,6 @@ function setupServices(syncManager: SyncManager) {
|
|||||||
const provider = getProviderWithNetId(netId, rpcUrl, config);
|
const provider = getProviderWithNetId(netId, rpcUrl, config);
|
||||||
|
|
||||||
const {
|
const {
|
||||||
tokens,
|
|
||||||
nativeCurrency,
|
nativeCurrency,
|
||||||
routerContract,
|
routerContract,
|
||||||
echoContract,
|
echoContract,
|
||||||
@ -229,56 +213,31 @@ function setupServices(syncManager: SyncManager) {
|
|||||||
logger,
|
logger,
|
||||||
});
|
});
|
||||||
|
|
||||||
services.tornadoServices = {} as TornadoServices;
|
const instances = getMultiInstances(netId, config);
|
||||||
|
|
||||||
for (const currency of getActiveTokens(config)) {
|
const [firstInstance, { amount, currency }] = Object.entries(instances)[0];
|
||||||
const currencyConfig = tokens[currency];
|
|
||||||
|
|
||||||
const currencyService = (services.tornadoServices[currency] = {} as CurrencyServices);
|
services.tornadoServices = new NodeMultiTornadoService({
|
||||||
|
|
||||||
for (const [amount, instanceAddress] of Object.entries(currencyConfig.instanceAddress)) {
|
|
||||||
const Tornado = Tornado__factory.connect(instanceAddress, provider);
|
|
||||||
|
|
||||||
const amountService = (currencyService[amount] = {} as AmountsServices);
|
|
||||||
|
|
||||||
const TornadoServiceConstructor = {
|
|
||||||
netId,
|
netId,
|
||||||
provider,
|
provider,
|
||||||
Tornado,
|
instances,
|
||||||
amount,
|
|
||||||
currency,
|
|
||||||
deployedBlock,
|
deployedBlock,
|
||||||
cacheDirectory,
|
|
||||||
userDirectory,
|
|
||||||
nativeCurrency,
|
|
||||||
logger,
|
|
||||||
};
|
|
||||||
|
|
||||||
amountService.depositsService = new NodeTornadoService({
|
|
||||||
...TornadoServiceConstructor,
|
|
||||||
merkleTreeService: new MerkleTreeService({
|
merkleTreeService: new MerkleTreeService({
|
||||||
netId,
|
netId,
|
||||||
amount,
|
amount,
|
||||||
currency,
|
currency,
|
||||||
Tornado,
|
Tornado: Tornado__factory.connect(firstInstance, provider),
|
||||||
merkleWorkerPath,
|
merkleWorkerPath,
|
||||||
}),
|
}),
|
||||||
treeCache: new TreeCache({
|
treeCache: new TreeCache({
|
||||||
netId,
|
|
||||||
amount,
|
|
||||||
currency,
|
|
||||||
userDirectory: userTreeDir,
|
userDirectory: userTreeDir,
|
||||||
}),
|
}),
|
||||||
optionalTree: true,
|
optionalTree: true,
|
||||||
type: 'Deposit',
|
nativeCurrency,
|
||||||
|
cacheDirectory,
|
||||||
|
userDirectory,
|
||||||
|
logger,
|
||||||
});
|
});
|
||||||
|
|
||||||
amountService.withdrawalsService = new NodeTornadoService({
|
|
||||||
...TornadoServiceConstructor,
|
|
||||||
type: 'Withdrawal',
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
syncManager.cachedServices = cachedServices;
|
syncManager.cachedServices = cachedServices;
|
||||||
@ -413,12 +372,11 @@ export async function syncNetworkEvents(syncManager: SyncManager, netId: NetIdTy
|
|||||||
|
|
||||||
const eventsStatus = {
|
const eventsStatus = {
|
||||||
governance: governanceService ? {} : undefined,
|
governance: governanceService ? {} : undefined,
|
||||||
registered: registryService ? {} : undefined,
|
|
||||||
registry: registryService ? {} : undefined,
|
registry: registryService ? {} : undefined,
|
||||||
revenue: revenueService ? {} : undefined,
|
revenue: revenueService ? {} : undefined,
|
||||||
echo: {},
|
echo: {},
|
||||||
encrypted_notes: {},
|
encrypted_notes: {},
|
||||||
instances: {},
|
tornado: {},
|
||||||
} as TovarishEventsStatus;
|
} as TovarishEventsStatus;
|
||||||
|
|
||||||
if (governanceService) {
|
if (governanceService) {
|
||||||
@ -447,12 +405,6 @@ export async function syncNetworkEvents(syncManager: SyncManager, netId: NetIdTy
|
|||||||
{
|
{
|
||||||
const { lastBlock, timestamp, relayers } = await registryService.updateRelayers();
|
const { lastBlock, timestamp, relayers } = await registryService.updateRelayers();
|
||||||
|
|
||||||
eventsStatus.registered = {
|
|
||||||
lastBlock,
|
|
||||||
timestamp,
|
|
||||||
relayers: relayers.length,
|
|
||||||
};
|
|
||||||
|
|
||||||
logger.info(
|
logger.info(
|
||||||
`${netId}: Updated registry relayers (total: ${relayers.length}, block: ${lastBlock}, timestamp: ${timestamp})`,
|
`${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})`,
|
`${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) {
|
eventsStatus.tornado = {
|
||||||
const currencyStatus = (eventsStatus.instances[currency] = {} as InstanceEventsStatus);
|
events: tornadoEvents.events.length,
|
||||||
|
lastBlock: tornadoEvents.lastBlock,
|
||||||
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,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
logger.info(
|
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;
|
cachedEvents[netId] = eventsStatus;
|
||||||
|
|
||||||
syncStatus[netId].events = true;
|
syncStatus[netId].events = true;
|
||||||
|
@ -10,9 +10,6 @@ import type { NetIdType } from '@tornado/core';
|
|||||||
import { saveUserFile } from './data';
|
import { saveUserFile } from './data';
|
||||||
|
|
||||||
export interface TreeCacheConstructor {
|
export interface TreeCacheConstructor {
|
||||||
netId: NetIdType;
|
|
||||||
amount: string;
|
|
||||||
currency: string;
|
|
||||||
userDirectory: string;
|
userDirectory: string;
|
||||||
PARTS_COUNT?: number;
|
PARTS_COUNT?: number;
|
||||||
LEAVES?: number;
|
LEAVES?: number;
|
||||||
@ -29,30 +26,46 @@ export interface treeMetadata {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export class TreeCache {
|
export class TreeCache {
|
||||||
netId: NetIdType;
|
|
||||||
amount: string;
|
|
||||||
currency: string;
|
|
||||||
userDirectory: string;
|
userDirectory: string;
|
||||||
|
|
||||||
PARTS_COUNT: number;
|
PARTS_COUNT: number;
|
||||||
|
|
||||||
constructor({ netId, amount, currency, userDirectory, PARTS_COUNT = 4 }: TreeCacheConstructor) {
|
constructor({ userDirectory, PARTS_COUNT = 4 }: TreeCacheConstructor) {
|
||||||
this.netId = netId;
|
|
||||||
this.amount = amount;
|
|
||||||
this.currency = currency;
|
|
||||||
this.userDirectory = userDirectory;
|
this.userDirectory = userDirectory;
|
||||||
|
|
||||||
this.PARTS_COUNT = PARTS_COUNT;
|
this.PARTS_COUNT = PARTS_COUNT;
|
||||||
}
|
}
|
||||||
|
|
||||||
getInstanceName(): string {
|
static getInstanceName({
|
||||||
return `deposits_${this.netId}_${this.currency}_${this.amount}`;
|
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);
|
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
|
// events indexed by commitment
|
||||||
const eventsData = events.reduce(
|
const eventsData = events.reduce(
|
||||||
@ -90,7 +103,7 @@ export class TreeCache {
|
|||||||
2,
|
2,
|
||||||
) + '\n';
|
) + '\n';
|
||||||
|
|
||||||
const fileName = `${this.getInstanceName()}_slice${index + 1}.json`;
|
const fileName = `${instance}_slice${index + 1}.json`;
|
||||||
|
|
||||||
await saveUserFile({
|
await saveUserFile({
|
||||||
fileName,
|
fileName,
|
||||||
@ -102,7 +115,7 @@ export class TreeCache {
|
|||||||
|
|
||||||
const dataString = bloom.serialize() + '\n';
|
const dataString = bloom.serialize() + '\n';
|
||||||
|
|
||||||
const fileName = `${this.getInstanceName()}_bloom.json`;
|
const fileName = `${instance}_bloom.json`;
|
||||||
|
|
||||||
await saveUserFile({
|
await saveUserFile({
|
||||||
fileName,
|
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"
|
"@openzeppelin/contracts-v3" "npm:@openzeppelin/contracts@3.2.0-rc.0"
|
||||||
ethers "^6.13.4"
|
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"
|
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:
|
dependencies:
|
||||||
"@ensdomains/content-hash" "2.5.7"
|
"@ensdomains/content-hash" "2.5.7"
|
||||||
"@metamask/eth-sig-util" "^8.0.0"
|
"@metamask/eth-sig-util" "^8.0.0"
|
||||||
|
Loading…
Reference in New Issue
Block a user