Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
83 changes: 83 additions & 0 deletions packages/bitcore-node/scripts/reloadConfig.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
#!/bin/sh

dir=$(pwd)

if [ $# = 0 ]; then
pid_paths=$dir/pids/*

for path in $pid_paths; do
pid=$(cat "$path")
printf "$(basename "$path" .pid)::$pid "
pids="$pids $pid"
done
echo ''

kill -USR1 $pids &&
echo "Refreshed all workers"
exit 0
fi

if [ $1 = --help ]; then
cat << EOF
Usage: $(basename "$0") [OPTIONS] [WORKER...]

Reload configuration for bitcore workers

Options:
--help Show this help message and exit
list List all running workers

Arguments:
WORKER Name(s) of worker(s) to reload configs (e.g., all api p2p)
If no worker is specified, reload all running workers configs.

Examples:
$(basename "$0") Reload config for all workers
$(basename "$0") api p2p Reload config for 'api' and 'p2p' workers
$(basename "$0") list List all running workers
EOF
exit 0
fi

if [ $1 = list ]; then
pid_paths=$(ls $dir/pids/*.pid 2>/dev/null)
for path in $pid_paths; do
worker=$(basename "$path" .pid)
pid=$(cat "$path")
printf "%-3s %s\n" "$worker" "$pid"
done
exit 0
fi

for worker in $@; do
if [ ! -f "$dir/pids/$worker.pid" ]; then
echo "$worker is not running\n$worker.pid not found in $dir/pids"
case $worker in
all|api|p2p) ;;
*)
echo "$worker is not a standard worker\nstandard workers: all, api, p2p"
;;
esac
exit 1
fi
done

pid_paths=$(
for worker in $@; do
printf "$dir/pids/$worker.pid "
done
)

pids=$(
for path in $pid_paths; do
cat $path
printf ' '
done
)

kill -USR1 $pids &&

cat << EOF
Sent reload signal(s) SIGUSR1 to '$@'
pids: $pids
EOF
8 changes: 5 additions & 3 deletions packages/bitcore-node/src/config.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import cluster from 'cluster';
import fs from 'fs';
import { cpus, homedir } from 'os';
import path from 'path';
Expand Down Expand Up @@ -26,7 +27,8 @@ function findConfig(): ConfigType | undefined {
}
bitcoreConfigPath = path.join(bitcoreConfigPath, 'bitcore.config.json');
}
logger.info('Using config at: ' + bitcoreConfigPath);

logger.info(`${cluster.isPrimary ? 'Main' : 'Child'} ${process.pid} using config at: ${path.resolve(bitcoreConfigPath)}`);

let rawBitcoreConfig;
try {
Expand Down Expand Up @@ -62,7 +64,7 @@ function setTrustedPeers(config: ConfigType): ConfigType {
}
return config;
}
const Config = function(): ConfigType {
const loadConfig = function(): ConfigType {
let config: ConfigType = {
maxPoolSize: 50,
port: 3000,
Expand Down Expand Up @@ -129,4 +131,4 @@ const Config = function(): ConfigType {
return config;
};

export default Config();
export default loadConfig;
35 changes: 35 additions & 0 deletions packages/bitcore-node/src/modules/bitcoin/p2p.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { StateStorage } from '../../models/state';
import { TransactionStorage } from '../../models/transaction';
import { ChainStateProvider } from '../../providers/chain-state';
import { Libs } from '../../providers/libs';
import { Config } from '../../services/config';
import { BaseP2PWorker } from '../../services/p2p';
import { SpentHeightIndicators } from '../../types/Coin';
import { IUtxoNetworkConfig } from '../../types/Config';
Expand Down Expand Up @@ -57,6 +58,10 @@ export class BitcoinP2PWorker extends BaseP2PWorker<IBtcBlock> {
network: this.network,
messages: this.messages
});

process.on('SIGUSR1', async () => {
await this.reload();
});
}

cacheInv(type: number, hash: string): void {
Expand Down Expand Up @@ -186,6 +191,36 @@ export class BitcoinP2PWorker extends BaseP2PWorker<IBtcBlock> {
}
}

async reload() {
this.chainConfig = Config.chainConfig({ chain: this.chain, network: this.network }) as IUtxoNetworkConfig;
const configPeerUris: string[] = [];

for (const peer of Object.values(this.chainConfig.trustedPeers) as any[]) {
const uri = peer.host + ':' + peer.port;
configPeerUris.push(uri);
const hashes = Object.values(this.pool._addrs).map((a: any) => a.hash);
const addr = this.pool._addAddr({ ip: { v4: peer.host }, port: peer.port });
if (!hashes.includes(addr.hash)) {
logger.info(`Adding peer ${uri}`);
}
}

for (const addr of Object.values(this.pool._addrs) as any[]) {
const uri = addr.ip.v4 + ':' + addr.port;
if (!configPeerUris.includes(uri)) {
this.pool._addrs = (this.pool._addrs as any[]).filter(({ hash }) => hash !== addr.hash);
if (this.pool._connectedPeers[addr.hash]) {
logger.info(`Removing peer ${uri}`);
} else {
logger.info(`Removing unconnected peer ${uri}`);
continue;
}
this.pool._connectedPeers[addr.hash].disconnect();
delete this.pool._connectedPeers[addr.hash];
}
};
}

public async getHeaders(candidateHashes: string[]): Promise<BitcoinHeaderObj[]> {
let received = false;
return new Promise<BitcoinHeaderObj[]>(async resolve => {
Expand Down
25 changes: 16 additions & 9 deletions packages/bitcore-node/src/modules/moralis/api/csp.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import os from 'os';
import request from 'request';
import Web3 from 'web3';
import config from '../../../config';
import { Config } from '../../../../src/services/config';
import logger from '../../../logger';
import { MongoBound } from '../../../models/base';
import { CacheStorage } from '../../../models/cache';
Expand All @@ -19,8 +19,6 @@ import { GetBlockBeforeTimeParams, GetBlockParams, StreamAddressUtxosParams, Str
import { isDateValid } from '../../../utils';
import { ReadableWithEventPipe } from '../../../utils/streamWithEventPipe';



export interface MoralisAddressSubscription {
id?: string;
message?: string;
Expand All @@ -30,17 +28,26 @@ export interface MoralisAddressSubscription {
export class MoralisStateProvider extends BaseEVMStateProvider {
baseUrl = 'https://deep-index.moralis.io/api/v2.2';
baseStreamUrl = 'https://api.moralis-streams.com/streams/evm';
apiKey = config.externalProviders?.moralis?.apiKey;
baseWebhookurl = config.externalProviders?.moralis?.webhookBaseUrl;
headers = {
'Content-Type': 'application/json',
'X-API-Key': this.apiKey,
};
apiKey;
baseWebhookurl;
headers;

constructor(chain: string) {
super(chain);
this.loadConfig();
}

loadConfig() {
const config = Config.get();
this.apiKey = config.externalProviders?.moralis?.apiKey;
this.baseWebhookurl = config.externalProviders?.moralis?.webhookBaseUrl;
this.headers = {
'Content-Type': 'application/json',
'X-API-Key': this.apiKey,
};
}


// @override
async getBlockBeforeTime(params: GetBlockBeforeTimeParams): Promise<IBlock|null> {
const { chain, network, time } = params;
Expand Down
4 changes: 2 additions & 2 deletions packages/bitcore-node/src/modules/ripple/api/csp.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,12 @@ import {
TransactionMetadata
} from 'xrpl/dist/npm/models/transactions';
import { Node } from 'xrpl/dist/npm/models/transactions/metadata';
import Config from '../../../config';
import logger from '../../../logger';
import { CacheStorage } from '../../../models/cache';
import { ICoin } from '../../../models/coin';
import { WalletAddressStorage } from '../../../models/walletAddress';
import { InternalStateProvider } from '../../../providers/chain-state/internal/internal';
import { Config } from '../../../services/config';
import { Storage } from '../../../services/storage';
import { IBlock } from '../../../types/Block';
import { ChainNetwork } from '../../../types/ChainNetwork';
Expand Down Expand Up @@ -44,7 +44,7 @@ export class RippleStateProvider extends InternalStateProvider implements IChain

constructor(public chain: string = 'XRP') {
super(chain, RippleDbWalletTransactions);
this.config = Config.chains[this.chain];
this.config = Config.get().chains[this.chain];
}

async getClient(network: string) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ import { ObjectID } from 'mongodb';
import Web3 from 'web3';
import { Transaction } from 'web3-eth';
import { AbiItem } from 'web3-utils';
import Config from '../../../../config';
import {
historical,
internal,
Expand All @@ -15,6 +14,7 @@ import { ITransaction } from '../../../../models/baseTransaction';
import { CacheStorage } from '../../../../models/cache';
import { WalletAddressStorage } from '../../../../models/walletAddress';
import { InternalStateProvider } from '../../../../providers/chain-state/internal/internal';
import { Config } from '../../../../services/config';
import { Storage } from '../../../../services/storage';
import { IBlock } from '../../../../types/Block';
import { ChainId } from '../../../../types/ChainNetwork';
Expand Down Expand Up @@ -69,7 +69,7 @@ export class BaseEVMStateProvider extends InternalStateProvider implements IChai

constructor(public chain: string = 'ETH') {
super(chain);
this.config = Config.chains[this.chain] as IChainConfig<IEVMNetworkConfig>;
this.config = Config.get().chains[this.chain] as IChainConfig<IEVMNetworkConfig>;
}

async getWeb3(network: string, params?: { type: IProvider['dataType'] }): Promise<GetWeb3Response> {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import cors from 'cors';
import { Router } from 'express';
import Web3 from 'web3';
import config from '../../../../config';
import logger from '../../../../logger';
import { WebhookStorage } from '../../../../models/webhook';
import { Config } from '../../../../services/config';
Expand Down Expand Up @@ -231,7 +230,7 @@ export class EVMRouter {


private _validateMoralisWebhook(req, res, next) {
const secret = config.externalProviders?.moralis?.streamSecret;
const secret = Config.get().externalProviders?.moralis?.streamSecret;
if (!secret) {
return res.status(404).send('Moralis not configured');
}
Expand All @@ -247,7 +246,7 @@ export class EVMRouter {
}

private postMoralisWebhook(router: Router) {
const webhookCors = config.externalProviders?.moralis?.webhookCors;
const webhookCors = Config.get().externalProviders?.moralis?.webhookCors;
router.post(`/webhook/${this.chain}/:network/moralis`, cors(webhookCors), this._validateMoralisWebhook, async (req, res) => {
try {
const { network } = req.params;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,9 @@ import * as os from 'os';
import { Worker as Thread, threadId } from 'worker_threads';
import { CryptoRpc } from 'crypto-rpc';
import { ChainStateProvider } from '../../';
import Config from '../../../../config';
import logger, { timestamp } from '../../../../logger';
import { StateStorage } from '../../../../models/state';
import { Config } from '../../../../services/config';
import { IEVMNetworkConfig } from '../../../../types/Config';
import { wait } from '../../../../utils';
import { EVMBlockStorage } from '../models/block';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,9 @@ import { TokenListProvider } from '@solana/spl-token-registry';
import { CryptoRpc } from 'crypto-rpc';
import { SolRpc } from 'crypto-rpc/lib/sol/SolRpc';
import { instructionKeys } from 'crypto-rpc/lib/sol/transaction-parser';
import Config from '../../../../config';
import logger from '../../../../logger';
import { CacheStorage } from '../../../../models/cache';
import { Config } from '../../../../services/config';
import { IBlock } from '../../../../types/Block';
import { CoinListingJSON } from '../../../../types/Coin';
import { IChainConfig, IProvider, ISVMNetworkConfig } from '../../../../types/Config';
Expand All @@ -29,7 +29,7 @@ export class BaseSVMStateProvider extends InternalStateProvider implements IChai

constructor(public chain: string = 'SOL') {
super(chain);
this.config = Config.chains[this.chain] as IChainConfig<ISVMNetworkConfig>;
this.config = Config.get().chains[this.chain] as IChainConfig<ISVMNetworkConfig>;
}

async getRpc(network: string, params?: { type: IProvider['dataType'] }): Promise<GetSolWeb3Response> {
Expand Down
4 changes: 2 additions & 2 deletions packages/bitcore-node/src/routes/api/fee.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import express, { Request, Response } from 'express';
import config from '../../config';
import { Config } from '../../../src/services/config';
import logger from '../../logger';
import { ChainStateProvider } from '../../providers/chain-state';
import { QueryType } from '../../types/Api';
Expand Down Expand Up @@ -35,7 +35,7 @@ router.get('/:target', CacheMiddleware(CacheTimes.Second), async (req: Request,
return res.status(400).send('invalid target specified');
}
if (!mode) {
mode = (config.chains[chain]?.[network] as IUtxoNetworkConfig)?.defaultFeeMode;
mode = (Config.get().chains[chain]?.[network] as IUtxoNetworkConfig)?.defaultFeeMode;
} else if (!feeModes[chain]) {
mode = undefined;
} else if (!feeModes[chain]?.includes(mode)) {
Expand Down
4 changes: 2 additions & 2 deletions packages/bitcore-node/src/routes/api/wallet.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { Validation } from 'crypto-wallet-core';
import { Request, Response, Router } from 'express';
import config from '../../config';
import { Config } from '../../../src/services/config';
import logger from '../../logger';
import { ChainStateProvider } from '../../providers/chain-state';
import { StreamWalletAddressesParams } from '../../types/namespaces/ChainStateProvider';
Expand Down Expand Up @@ -112,7 +112,7 @@ router.post('/:pubKey', Auth.authenticateMiddleware, async (req: AuthenticatedRe
if (req.headers['x-reprocess']) {
const reprocessOk = Auth.verifyRequestSignature({
message: ['reprocess', '/addAddresses' + pubKey, JSON.stringify(req.body)].join('|'),
pubKey: config.services.socket.bwsKeys[0],
pubKey: Config.get().services.socket.bwsKeys[0],
signature: req.headers['x-reprocess']
});
if (!reprocessOk) {
Expand Down
3 changes: 1 addition & 2 deletions packages/bitcore-node/src/routes/index.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import cors from 'cors';
import express from 'express';
import config from '../config';
import { Config } from '../services/config';
import * as apiRoutes from './api';
import { CacheMiddleware, CacheTimes, LogMiddleware, RateLimiter } from './middleware';
Expand All @@ -24,7 +23,7 @@ app.use(
const chains = Config.chains();
const networks: any = {};
for (const chain of chains) {
for (const network of Object.keys(config.chains[chain])) {
for (const network of Object.keys(Config.get().chains[chain])) {
networks[chain] = networks[chain] || {};
Object.assign(networks[chain], {
[network]: true
Expand Down
6 changes: 3 additions & 3 deletions packages/bitcore-node/src/routes/status.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import express from 'express';
import config from '../config';
import { Config } from '../../src/services/config';
import { PerformanceTracker } from '../decorators/Loggify';
import { StateStorage } from '../models/state';
import { ChainNetwork } from '../types/ChainNetwork';
Expand All @@ -8,8 +8,8 @@ const router = express.Router({ mergeParams: true });

router.get('/enabled-chains', function(_, res) {
const chainNetworks = new Array<ChainNetwork>();
for (const chain of Object.keys(config.chains)) {
for (const network of Object.keys(config.chains[chain])) {
for (const chain of Object.keys(Config.get().chains)) {
for (const network of Object.keys(Config.get().chains[chain])) {
chainNetworks.push({ chain, network });
}
}
Expand Down
Loading