watcher-ts/packages/util/src/config.ts
prathamesh0 2e1652d772
Block connections with blacklisted multiaddrs (#373)
* Block connections from blacklisted multiaddrs in relay node

* Block connections from blacklisted multiaddrs in peer nodes

* Block dials for blacklisted multiaddrs

* Update package version
2023-05-04 16:33:29 +05:30

241 lines
5.8 KiB
TypeScript

//
// Copyright 2021 Vulcanize, Inc.
//
import assert from 'assert';
import fs from 'fs-extra';
import path from 'path';
import toml from 'toml';
import debug from 'debug';
import { ConnectionOptions } from 'typeorm';
import { Config as CacheConfig, getCache } from '@cerc-io/cache';
import { EthClient } from '@cerc-io/ipld-eth-client';
import { JsonRpcProvider } from '@ethersproject/providers';
import { getCustomProvider } from './misc';
const log = debug('vulcanize:config');
export interface JobQueueConfig {
dbConnectionString: string;
maxCompletionLagInSecs: number;
jobDelayInMilliSecs?: number;
eventsInBatch: number;
lazyUpdateBlockProgress?: boolean;
subgraphEventsOrder: boolean;
blockDelayInMilliSecs: number;
prefetchBlocksInMem: boolean;
prefetchBlockCount: number;
}
export interface GQLCacheConfig {
enabled: boolean;
maxCacheSize?: number;
maxAge: number;
timeTravelMaxAge: number;
}
// Relay node config
export interface RelayConfig {
// Host to bind the relay server to
host?: string;
// Port to start listening on
port?: number;
// Relay peer id file path (json)
peerIdFile?: string;
// Domain name to be used in the announce address
announce?: string;
// Relay peer multiaddr(s) list
relayPeers?: string[];
// Blacklisted multiaddr(s) list
denyMultiaddrs?: string[];
// Timeout (ms) for dial to relay peers
dialTimeout?: number;
// Interval in ms to check relay peer connections using ping
pingInterval?: number;
// Redial interval in ms on connection failure
redialInterval?: number;
// Max number of dial retries to be attempted to a relay peer
maxDialRetry?: number;
// Broadcast node's info over floodsub on requests
enableDebugInfo?: boolean;
}
// L2 tx config
interface L2TxsConfig {
// Address of contract for which txs are sent
contractAddress: string;
// Private key of tx signer (needs to have some balance)
privateKey: string;
// Gas limit for tx
gasLimit?: number
}
// Peer config
export interface PeerConfig {
// Multiaddr of the primary relay node for this peer
relayMultiaddr: string;
// Pubsub topic to subscribe this peer to
pubSubTopic: string;
// Interval (ms) to check relay peer connections using ping
pingInterval?: number;
// Ping timeout (ms) used to check if connection is alive
pingTimeout?: number;
// Max number of relay node connections for a peer
maxRelayConnections?: number;
// Redial interval (ms) to relay node on connection failure
relayRedialInterval?: number;
// Blacklisted multiaddr(s) list
denyMultiaddrs?: string[];
// Max number of connections for a peer
maxConnections?: number;
// Timeout (ms) for dial to peers
dialTimeout?: number;
// Peer id file path (json)
peerIdFile?: string;
// Participate in exchange of debug info over floodsub
enableDebugInfo?: boolean;
// Enable sending txs to L2 chain for every message received in P2P network
enableL2Txs: boolean;
// Config for sending txs to L2
l2TxsConfig?: L2TxsConfig;
}
// P2P config
export interface P2PConfig {
// Enable relay node
enableRelay: boolean;
relay: RelayConfig;
// Enable peer node
enablePeer: boolean;
peer: PeerConfig;
}
export interface ServerConfig {
host: string;
port: number;
mode: string;
kind: string;
checkpointing: boolean;
checkpointInterval: number;
subgraphPath: string;
enableState: boolean;
wasmRestartBlocksInterval: number;
filterLogs: boolean;
maxEventsBlockRange: number;
clearEntitiesCacheInterval: number;
// Boolean to skip updating entity fields required in state creation and not required in the frontend.
skipStateFieldsUpdate: boolean;
// Max GQL API requests to process simultaneously (defaults to 1).
maxSimultaneousRequests?: number;
// Max GQL API requests in queue until reject (defaults to -1, means do not reject).
maxRequestQueueLimit?: number;
// Boolean to load GQL query nested entity relations sequentially.
loadRelationsSequential: boolean;
// GQL cache-control max-age settings (in seconds)
gqlCache: GQLCacheConfig;
p2p: P2PConfig;
}
export interface UpstreamConfig {
cache: CacheConfig;
ethServer: {
gqlApiEndpoint: string;
rpcProviderEndpoint: string;
}
traceProviderEndpoint: string;
}
export interface GQLMetricsConfig {
port: number;
}
export interface MetricsConfig {
host: string;
port: number;
gql: GQLMetricsConfig;
}
export interface Config {
server: ServerConfig;
database: ConnectionOptions;
upstream: UpstreamConfig;
jobQueue: JobQueueConfig;
metrics: MetricsConfig;
}
export const getConfig = async<ConfigType> (configFile: string): Promise<ConfigType> => {
const configFilePath = path.resolve(configFile);
const fileExists = await fs.pathExists(configFilePath);
if (!fileExists) {
throw new Error(`Config file not found: ${configFilePath}`);
}
const config = toml.parse(await fs.readFile(configFilePath, 'utf8'));
log('config', JSON.stringify(config, null, 2));
return config;
};
export const initClients = async (config: Config): Promise<{
ethClient: EthClient,
ethProvider: JsonRpcProvider
}> => {
const { database: dbConfig, upstream: upstreamConfig, server: serverConfig } = config;
assert(serverConfig, 'Missing server config');
assert(dbConfig, 'Missing database config');
assert(upstreamConfig, 'Missing upstream config');
const { ethServer: { gqlApiEndpoint, rpcProviderEndpoint }, cache: cacheConfig } = upstreamConfig;
assert(gqlApiEndpoint, 'Missing upstream ethServer.gqlApiEndpoint');
assert(rpcProviderEndpoint, 'Missing upstream ethServer.rpcProviderEndpoint');
const cache = await getCache(cacheConfig);
const ethClient = new EthClient({
gqlEndpoint: gqlApiEndpoint,
cache
});
const ethProvider = getCustomProvider(rpcProviderEndpoint);
return {
ethClient,
ethProvider
};
};