From 640310c2e0430231c956f9df42883935d0cdf40d Mon Sep 17 00:00:00 2001 From: Micah Riggan Date: Wed, 26 Dec 2018 16:31:14 -0500 Subject: [PATCH 1/9] feat(node): dependency injection / config Injecting dependencies via constructor and disabling services from config Wallet exports different now Multi-sig script Removing config reloading option Remove debug code --- .../bin/multi-sig/wallet-derive-address | 2 +- packages/bitcore-client/bin/wallet-balance | 2 +- packages/bitcore-client/bin/wallet-broadcast | 2 +- packages/bitcore-client/bin/wallet-create | 2 +- packages/bitcore-client/bin/wallet-decrypt | 2 +- packages/bitcore-client/bin/wallet-derive | 2 +- packages/bitcore-client/bin/wallet-import | 2 +- packages/bitcore-client/bin/wallet-list | 2 +- packages/bitcore-client/bin/wallet-register | 2 +- packages/bitcore-client/bin/wallet-sign | 2 +- .../bin/wallet-transaction-list | 2 +- packages/bitcore-client/bin/wallet-tx | 2 +- packages/bitcore-client/bin/wallet-utxos | 2 +- packages/bitcore-node/src/config.ts | 35 ++++-- packages/bitcore-node/src/models/base.ts | 12 +- packages/bitcore-node/src/models/block.ts | 9 +- packages/bitcore-node/src/models/coin.ts | 9 +- packages/bitcore-node/src/models/events.ts | 9 +- packages/bitcore-node/src/models/rateLimit.ts | 15 +-- packages/bitcore-node/src/models/state.ts | 9 +- .../bitcore-node/src/models/transaction.ts | 20 ++-- packages/bitcore-node/src/models/wallet.ts | 14 ++- .../bitcore-node/src/models/walletAddress.ts | 11 +- .../chain-state/internal/internal.ts | 8 +- .../bitcore-node/src/routes/api/wallet.ts | 4 +- .../bitcore-node/src/routes/middleware.ts | 4 +- packages/bitcore-node/src/server.ts | 34 +++--- packages/bitcore-node/src/services/api.ts | 56 +++++++--- packages/bitcore-node/src/services/config.ts | 33 ++++++ packages/bitcore-node/src/services/event.ts | 56 ++++++++-- packages/bitcore-node/src/services/p2p.ts | 105 ++++++++++++++---- packages/bitcore-node/src/services/socket.ts | 47 ++++++-- packages/bitcore-node/src/services/storage.ts | 23 ++-- packages/bitcore-node/src/types/Config.d.ts | 33 ++++-- 34 files changed, 397 insertions(+), 175 deletions(-) create mode 100644 packages/bitcore-node/src/services/config.ts diff --git a/packages/bitcore-client/bin/multi-sig/wallet-derive-address b/packages/bitcore-client/bin/multi-sig/wallet-derive-address index f8ea4dddb45..f0f5b154def 100755 --- a/packages/bitcore-client/bin/multi-sig/wallet-derive-address +++ b/packages/bitcore-client/bin/multi-sig/wallet-derive-address @@ -3,7 +3,7 @@ const fs = require('fs'); const bitcoreLib = require('bitcore-lib'); const program = require('commander'); -const Wallet = require('../../lib/wallet'); +const { Wallet } = require('../../lib/wallet'); const promptly = require('promptly'); program diff --git a/packages/bitcore-client/bin/wallet-balance b/packages/bitcore-client/bin/wallet-balance index 056c75dbd69..0cb62468dec 100755 --- a/packages/bitcore-client/bin/wallet-balance +++ b/packages/bitcore-client/bin/wallet-balance @@ -1,7 +1,7 @@ #!/usr/bin/env node const program = require('../ts_build/program'); -const Wallet = require('../ts_build/wallet'); +const { Wallet } = require('../ts_build/wallet'); try { program diff --git a/packages/bitcore-client/bin/wallet-broadcast b/packages/bitcore-client/bin/wallet-broadcast index 87f95fc3b37..76641513b33 100755 --- a/packages/bitcore-client/bin/wallet-broadcast +++ b/packages/bitcore-client/bin/wallet-broadcast @@ -1,7 +1,7 @@ #!/usr/bin/env node const program = require('../ts_build/program'); -const Wallet = require('../ts_build/wallet'); +const { Wallet } = require('../ts_build/wallet'); program .version(require('../package.json').version) diff --git a/packages/bitcore-client/bin/wallet-create b/packages/bitcore-client/bin/wallet-create index c4a0648da3e..4fc42149da0 100755 --- a/packages/bitcore-client/bin/wallet-create +++ b/packages/bitcore-client/bin/wallet-create @@ -1,7 +1,7 @@ #!/usr/bin/env node const program = require('../ts_build/program'); -const Wallet = require('../ts_build/wallet'); +const { Wallet } = require('../ts_build/wallet'); const promptly = require('promptly'); program diff --git a/packages/bitcore-client/bin/wallet-decrypt b/packages/bitcore-client/bin/wallet-decrypt index 1a74876eaff..8cf8cce5a2e 100755 --- a/packages/bitcore-client/bin/wallet-decrypt +++ b/packages/bitcore-client/bin/wallet-decrypt @@ -1,7 +1,7 @@ #!/usr/bin/env node const program = require('../ts_build/program'); -const Wallet = require('../ts_build/wallet'); +const { Wallet } = require('../ts_build/wallet'); const promptly = require('promptly'); program diff --git a/packages/bitcore-client/bin/wallet-derive b/packages/bitcore-client/bin/wallet-derive index 5d819077e94..3ba0aee0cbd 100755 --- a/packages/bitcore-client/bin/wallet-derive +++ b/packages/bitcore-client/bin/wallet-derive @@ -5,7 +5,7 @@ const bitcoreLibs = { BCH: require('bitcore-lib-cash') }; const program = require('../ts_build/program'); -const Wallet = require('../ts_build/wallet'); +const { Wallet } = require('../ts_build/wallet'); const promptly = require('promptly'); program diff --git a/packages/bitcore-client/bin/wallet-import b/packages/bitcore-client/bin/wallet-import index b142f3cd8fa..d80de4e11c6 100755 --- a/packages/bitcore-client/bin/wallet-import +++ b/packages/bitcore-client/bin/wallet-import @@ -2,7 +2,7 @@ const fs = require('fs'); const program = require('../ts_build/program'); -const Wallet = require('../ts_build/wallet'); +const { Wallet } = require('../ts_build/wallet'); const promptly = require('promptly'); program diff --git a/packages/bitcore-client/bin/wallet-list b/packages/bitcore-client/bin/wallet-list index 3405dfcfad7..4e422b268c8 100755 --- a/packages/bitcore-client/bin/wallet-list +++ b/packages/bitcore-client/bin/wallet-list @@ -1,7 +1,7 @@ #!/usr/bin/env node 'use strict'; -const Storage = require('../ts_build/storage'); +const { Storage } = require('../ts_build/storage'); const program = require('../ts_build/program'); program diff --git a/packages/bitcore-client/bin/wallet-register b/packages/bitcore-client/bin/wallet-register index fed9326a353..99b941e5200 100755 --- a/packages/bitcore-client/bin/wallet-register +++ b/packages/bitcore-client/bin/wallet-register @@ -1,7 +1,7 @@ #!/usr/bin/env node const program = require('../ts_build/program'); -const Wallet = require('../ts_build/wallet'); +const { Wallet } = require('../ts_build/wallet'); program .version(require('../package.json').version) diff --git a/packages/bitcore-client/bin/wallet-sign b/packages/bitcore-client/bin/wallet-sign index d1ae233d669..588359f2b14 100755 --- a/packages/bitcore-client/bin/wallet-sign +++ b/packages/bitcore-client/bin/wallet-sign @@ -1,7 +1,7 @@ #!/usr/bin/env node const program = require('../ts_build/program'); -const Wallet = require('../ts_build/wallet'); +const { Wallet } = require('../ts_build/wallet'); const promptly = require('promptly'); program diff --git a/packages/bitcore-client/bin/wallet-transaction-list b/packages/bitcore-client/bin/wallet-transaction-list index 3979cef0a01..e97f3520233 100755 --- a/packages/bitcore-client/bin/wallet-transaction-list +++ b/packages/bitcore-client/bin/wallet-transaction-list @@ -1,7 +1,7 @@ #!/usr/bin/env node const program = require('../ts_build/program'); -const Wallet = require('../ts_build/wallet'); +const { Wallet } = require('../ts_build/wallet'); program .version(require('../package.json').version) diff --git a/packages/bitcore-client/bin/wallet-tx b/packages/bitcore-client/bin/wallet-tx index 327b181d6f4..a7311254e81 100755 --- a/packages/bitcore-client/bin/wallet-tx +++ b/packages/bitcore-client/bin/wallet-tx @@ -1,7 +1,7 @@ #!/usr/bin/env node const program = require('../ts_build/program'); -const Wallet = require('../ts_build/wallet'); +const { Wallet } = require('../ts_build/wallet'); program .version(require('../package.json').version) diff --git a/packages/bitcore-client/bin/wallet-utxos b/packages/bitcore-client/bin/wallet-utxos index df5f269125b..b1a37f282fa 100755 --- a/packages/bitcore-client/bin/wallet-utxos +++ b/packages/bitcore-client/bin/wallet-utxos @@ -1,7 +1,7 @@ #!/usr/bin/env node const program = require('../ts_build/program'); -const Wallet = require('../ts_build/wallet'); +const { Wallet } = require('../ts_build/wallet'); program .version(require('../package.json').version) diff --git a/packages/bitcore-node/src/config.ts b/packages/bitcore-node/src/config.ts index deceb89c3dc..ab129b5b8c4 100644 --- a/packages/bitcore-node/src/config.ts +++ b/packages/bitcore-node/src/config.ts @@ -1,6 +1,6 @@ import { homedir, cpus } from 'os'; import parseArgv from './utils/parseArgv'; -import ConfigType from './types/Config'; +import { ConfigType } from "./types/Config"; let program = parseArgv([], ['config']); function findConfig(): ConfigType | undefined { @@ -57,18 +57,31 @@ const Config = function(): ConfigType { dbName: process.env.DB_NAME || 'bitcore', dbPort: process.env.DB_PORT || '27017', numWorkers: cpus().length, - api: { - rateLimiter: { - whitelist: [ - '::ffff:127.0.0.1' - ] + chains: {}, + services: { + api: { + enabled: true, + rateLimiter: { + whitelist: ['::ffff:127.0.0.1'] + }, + wallets: { + allowCreationBeforeCompleteSync: false, + allowUnauthenticatedCalls: false + } + }, + event: { + enabled: true + }, + p2p: { + enabled: true }, - wallets: { - allowCreationBeforeCompleteSync: false, - allowUnauthenticatedCalls: false + socket: { + enabled: true + }, + storage: { + enabled: true } - }, - chains: {} + } }; let foundConfig = findConfig(); diff --git a/packages/bitcore-node/src/models/base.ts b/packages/bitcore-node/src/models/base.ts index cd4e77738bd..e3a3d3cc6b7 100644 --- a/packages/bitcore-node/src/models/base.ts +++ b/packages/bitcore-node/src/models/base.ts @@ -13,15 +13,15 @@ export abstract class BaseModel { key: keyof T; }>; - constructor(private collectionName: string) { + constructor(private collectionName: string, private storageService = Storage) { this.handleConnection(); } private async handleConnection() { - Storage.connection.on('CONNECTED', async () => { - if (Storage.db != undefined) { + this.storageService.connection.on('CONNECTED', async () => { + if (this.storageService.db != undefined) { this.connected = true; - this.db = Storage.db; + this.db = this.storageService.db; await this.onConnect(); } }); @@ -30,8 +30,8 @@ export abstract class BaseModel { abstract async onConnect(); get collection(): Collection> { - if (Storage.db) { - return Storage.db.collection(this.collectionName); + if (this.storageService.db) { + return this.storageService.db.collection(this.collectionName); } else { throw new Error('Not connected to the database yet'); } diff --git a/packages/bitcore-node/src/models/block.ts b/packages/bitcore-node/src/models/block.ts index e6d7dd6b350..05ea099a19a 100644 --- a/packages/bitcore-node/src/models/block.ts +++ b/packages/bitcore-node/src/models/block.ts @@ -11,13 +11,14 @@ import { SpentHeightIndicators } from '../types/Coin'; import { EventModel } from './events'; import config from '../config'; import { Event } from '../services/event'; +import { StorageService } from "../services/storage"; export { IBlock }; @LoggifyClass -export class Block extends BaseModel { - constructor() { - super('blocks'); +export class BlockSchema extends BaseModel { + constructor(storage?: StorageService) { + super('blocks', storage); } chainTips: Mapping> = {}; @@ -227,4 +228,4 @@ export class Block extends BaseModel { } } -export let BlockModel = new Block(); +export let BlockModel = new BlockSchema(); diff --git a/packages/bitcore-node/src/models/coin.ts b/packages/bitcore-node/src/models/coin.ts index 7b60111a715..3c9db75b33b 100644 --- a/packages/bitcore-node/src/models/coin.ts +++ b/packages/bitcore-node/src/models/coin.ts @@ -3,6 +3,7 @@ import { BaseModel, MongoBound } from './base'; import { ObjectID } from 'mongodb'; import { SpentHeightIndicators, CoinJSON } from '../types/Coin'; import { valueOrDefault } from '../utils/check'; +import { StorageService } from '../services/storage'; export type ICoin = { network: string; @@ -21,9 +22,9 @@ export type ICoin = { }; @LoggifyClass -class Coin extends BaseModel { - constructor() { - super('coins'); +class CoinSchema extends BaseModel { + constructor(storage?: StorageService) { + super('coins', storage); } allowedPaging = [ @@ -166,4 +167,4 @@ class Coin extends BaseModel { return JSON.stringify(transform); } } -export let CoinModel = new Coin(); +export let CoinModel = new CoinSchema(); diff --git a/packages/bitcore-node/src/models/events.ts b/packages/bitcore-node/src/models/events.ts index f75edf474cd..937b9bc9837 100644 --- a/packages/bitcore-node/src/models/events.ts +++ b/packages/bitcore-node/src/models/events.ts @@ -2,6 +2,7 @@ import { BaseModel } from './base'; import { ITransaction } from './transaction'; import { IBlock } from '../types/Block'; import { ICoin } from './coin'; +import { StorageService } from '../services/storage'; export namespace IEvent { export type BlockEvent = IBlock; @@ -13,9 +14,9 @@ interface IEvent { type: 'block' | 'tx' | 'coin'; emitTime: Date; } -class Event extends BaseModel { - constructor() { - super('events'); +export class EventSchema extends BaseModel { + constructor(storage?: StorageService) { + super('events', storage); } allowedPaging = []; @@ -53,4 +54,4 @@ class Event extends BaseModel { return this.collection.find({ type: 'coin', emitTime: { $gte: lastSeen } }).addCursorFlag('noCursorTimeout', true); } } -export const EventModel = new Event(); +export const EventModel = new EventSchema(); diff --git a/packages/bitcore-node/src/models/rateLimit.ts b/packages/bitcore-node/src/models/rateLimit.ts index 7292dac74d6..3d3051712c3 100644 --- a/packages/bitcore-node/src/models/rateLimit.ts +++ b/packages/bitcore-node/src/models/rateLimit.ts @@ -1,5 +1,6 @@ import { BaseModel } from './base'; import { ObjectID } from 'mongodb'; +import { StorageService } from '../services/storage'; export type IRateLimit = { _id?: ObjectID; @@ -11,9 +12,9 @@ export type IRateLimit = { expireAt?: Date; }; -export class RateLimit extends BaseModel { - constructor() { - super('ratelimits'); +export class RateLimitSchema extends BaseModel { + constructor(storage?: StorageService) { + super('ratelimits', storage); } allowedPaging = []; @@ -25,9 +26,9 @@ export class RateLimit extends BaseModel { incrementAndCheck(identifier: string, method: string) { return Promise.all([ this.collection.findOneAndUpdate( - { identifier, method, period: 'second', time: {$gt: new Date(Date.now() - 1000)} }, + { identifier, method, period: 'second', time: { $gt: new Date(Date.now() - 1000) } }, { - $setOnInsert: { time: new Date(), expireAt: new Date(Date.now() + 10 * 1000) }, + $setOnInsert: { time: new Date(), expireAt: new Date(Date.now() + 10 * 1000) }, $inc: { count: 1 } }, { upsert: true, returnOriginal: false } @@ -47,9 +48,9 @@ export class RateLimit extends BaseModel { $inc: { count: 1 } }, { upsert: true, returnOriginal: false } - ), + ) ]); } } -export let RateLimitModel = new RateLimit(); +export let RateLimitModel = new RateLimitSchema(); diff --git a/packages/bitcore-node/src/models/state.ts b/packages/bitcore-node/src/models/state.ts index cc0e44d3f11..9cc1e82177e 100644 --- a/packages/bitcore-node/src/models/state.ts +++ b/packages/bitcore-node/src/models/state.ts @@ -1,3 +1,4 @@ +import { StorageService } from '../services/storage'; import { BaseModel } from './base'; import { ObjectID } from 'mongodb'; @@ -6,13 +7,13 @@ export type IState = { initialSyncComplete: any; }; -export class State extends BaseModel { - constructor() { - super('state'); +export class StateSchema extends BaseModel { + constructor(storage?: StorageService) { + super('state', storage); } allowedPaging = []; onConnect() {} } -export let StateModel = new State(); +export let StateModel = new StateSchema(); diff --git a/packages/bitcore-node/src/models/transaction.ts b/packages/bitcore-node/src/models/transaction.ts index 408e70a14bf..a8505ad7faa 100644 --- a/packages/bitcore-node/src/models/transaction.ts +++ b/packages/bitcore-node/src/models/transaction.ts @@ -7,12 +7,12 @@ import { LoggifyClass } from '../decorators/Loggify'; import { Bitcoin } from '../types/namespaces/Bitcoin'; import { BaseModel, MongoBound } from './base'; import logger from '../logger'; -import config from '../config'; -import { StreamingFindOptions, Storage } from '../services/storage'; +import { StreamingFindOptions, Storage, StorageService } from '../services/storage'; import * as lodash from 'lodash'; import { Socket } from '../services/socket'; import { TransactionJSON } from '../types/Transaction'; import { SpentHeightIndicators } from '../types/Coin'; +import { Config } from '../services/config'; const Chain = require('../chain'); @@ -35,9 +35,9 @@ export type ITransaction = { }; @LoggifyClass -export class Transaction extends BaseModel { - constructor() { - super('transactions'); +export class TransactionSchema extends BaseModel { + constructor(storage?: StorageService) { + super('transactions', storage); } allowedPaging = [ @@ -82,7 +82,7 @@ export class Transaction extends BaseModel { logger.debug('Minting Coins', mintOps.length); if (mintOps.length) { await Promise.all( - partition(mintOps, mintOps.length / config.maxPoolSize).map(mintBatch => + partition(mintOps, mintOps.length / Config.current.maxPoolSize).map(mintBatch => CoinModel.collection.bulkWrite(mintBatch, { ordered: false }) ) ); @@ -91,7 +91,7 @@ export class Transaction extends BaseModel { logger.debug('Spending Coins', spendOps.length); if (spendOps.length) { await Promise.all( - partition(spendOps, spendOps.length / config.maxPoolSize).map(spendBatch => + partition(spendOps, spendOps.length / Config.current.maxPoolSize).map(spendBatch => CoinModel.collection.bulkWrite(spendBatch, { ordered: false }) ) ); @@ -101,7 +101,7 @@ export class Transaction extends BaseModel { const txOps = await this.addTransactions({ ...params, mintOps }); logger.debug('Writing Transactions', txOps.length); await Promise.all( - partition(txOps, txOps.length / config.maxPoolSize).map(txBatch => + partition(txOps, txOps.length / Config.current.maxPoolSize).map(txBatch => this.collection.bulkWrite(txBatch, { ordered: false }) ) ); @@ -334,7 +334,7 @@ export class Transaction extends BaseModel { } } - if (initialSyncComplete || config.api.wallets.allowCreationBeforeCompleteSync) { + if (initialSyncComplete || Config.for('api').wallets.allowCreationBeforeCompleteSync) { let mintOpsAddresses = {}; for (const mintOp of mintOps) { mintOpsAddresses[mintOp.updateOne.update.$set.address] = true; @@ -489,4 +489,4 @@ export class Transaction extends BaseModel { return JSON.stringify(transaction); } } -export let TransactionModel = new Transaction(); +export let TransactionModel = new TransactionSchema(); diff --git a/packages/bitcore-node/src/models/wallet.ts b/packages/bitcore-node/src/models/wallet.ts index 36033696050..7f376e159c8 100644 --- a/packages/bitcore-node/src/models/wallet.ts +++ b/packages/bitcore-node/src/models/wallet.ts @@ -2,6 +2,7 @@ import { WalletAddressModel } from '../models/walletAddress'; import { BaseModel } from './base'; import { TransformOptions } from '../types/TransformOptions'; import { ObjectID } from 'mongodb'; +import { StorageService } from '../services/storage'; export type IWallet = { _id?: ObjectID; @@ -13,9 +14,9 @@ export type IWallet = { path: string; }; -export class Wallet extends BaseModel { - constructor() { - super('wallets'); +export class WalletSchema extends BaseModel { + constructor(storage?: StorageService) { + super('wallets', storage); } allowedPaging = []; @@ -32,10 +33,13 @@ export class Wallet extends BaseModel { } async updateCoins(wallet: IWallet) { - let addressModels = await WalletAddressModel.collection.find({ wallet: wallet._id }).addCursorFlag('noCursorTimeout', true).toArray(); + let addressModels = await WalletAddressModel.collection + .find({ wallet: wallet._id }) + .addCursorFlag('noCursorTimeout', true) + .toArray(); let addresses = addressModels.map(model => model.address); return WalletAddressModel.updateCoins({ wallet, addresses }); } } -export let WalletModel = new Wallet(); +export let WalletModel = new WalletSchema(); diff --git a/packages/bitcore-node/src/models/walletAddress.ts b/packages/bitcore-node/src/models/walletAddress.ts index f3f4a3801e4..830f6b53ee8 100644 --- a/packages/bitcore-node/src/models/walletAddress.ts +++ b/packages/bitcore-node/src/models/walletAddress.ts @@ -4,6 +4,7 @@ import { ObjectID } from 'mongodb'; import { BaseModel } from './base'; import { IWallet } from './wallet'; import { TransactionModel } from './transaction'; +import { StorageService } from '../services/storage'; export type IWalletAddress = { wallet: ObjectID; @@ -12,9 +13,9 @@ export type IWalletAddress = { network: string; }; -export class WalletAddress extends BaseModel { - constructor() { - super('walletaddresses'); +export class WalletAddressSchema extends BaseModel { + constructor(storage?: StorageService) { + super('walletaddresses', storage); } allowedPaging = []; @@ -79,7 +80,7 @@ export class WalletAddress extends BaseModel { }; const ProcessBatch = batch => { - return Promise.all([ AddAddresses(batch), UpdateCoins(batch)]); + return Promise.all([AddAddresses(batch), UpdateCoins(batch)]); }; for (const address of addresses) { @@ -124,4 +125,4 @@ export class WalletAddress extends BaseModel { } } -export let WalletAddressModel = new WalletAddress(); +export let WalletAddressModel = new WalletAddressSchema(); diff --git a/packages/bitcore-node/src/providers/chain-state/internal/internal.ts b/packages/bitcore-node/src/providers/chain-state/internal/internal.ts index 6fbb5c301d0..cf415df0378 100644 --- a/packages/bitcore-node/src/providers/chain-state/internal/internal.ts +++ b/packages/bitcore-node/src/providers/chain-state/internal/internal.ts @@ -1,5 +1,4 @@ -import { TransactionJSON } from "../../../types/Transaction"; -import config from '../../../config'; +import { TransactionJSON } from '../../../types/Transaction'; import through2 from 'through2'; import { MongoBound } from '../../../models/base'; @@ -17,6 +16,7 @@ import { ListTransactionsStream } from './transforms'; import { StringifyJsonStream } from '../../../utils/stringifyJsonStream'; import { StateModel } from '../../../models/state'; import { SpentHeightIndicators, CoinJSON } from '../../../types/Coin'; +import { Config } from '../../../services/config'; @LoggifyClass export class InternalStateProvider implements CSP.IChainStateService { @@ -27,7 +27,7 @@ export class InternalStateProvider implements CSP.IChainStateService { } getRPC(chain: string, network: string) { - const RPC_PEER = config.chains[chain][network].rpc; + const RPC_PEER = Config.current.chains[chain][network].rpc; if (!RPC_PEER) { throw new Error(`RPC not configured for ${chain} ${network}`); } @@ -230,7 +230,7 @@ export class InternalStateProvider implements CSP.IChainStateService { const state = await StateModel.collection.findOne({}); const initialSyncComplete = state && state.initialSyncComplete && state.initialSyncComplete.includes(`${chain}:${network}`); - if (!initialSyncComplete && !config.api.wallets.allowCreationBeforeCompleteSync) { + if (!initialSyncComplete && !Config.for('api').wallets.allowCreationBeforeCompleteSync) { throw 'Wallet creation not permitted before intitial sync is complete'; } const wallet: IWallet = { diff --git a/packages/bitcore-node/src/routes/api/wallet.ts b/packages/bitcore-node/src/routes/api/wallet.ts index 578fa7ab9fb..75400092887 100644 --- a/packages/bitcore-node/src/routes/api/wallet.ts +++ b/packages/bitcore-node/src/routes/api/wallet.ts @@ -1,3 +1,4 @@ +import { Config } from "../../services/config"; import { Request, Response, Router } from 'express'; import { ChainNetwork } from '../../types/ChainNetwork'; import { IWallet } from '../../models/wallet'; @@ -5,7 +6,6 @@ import { RequestHandler } from 'express-serve-static-core'; import { ChainStateProvider } from '../../providers/chain-state'; import logger from '../../logger'; import { MongoBound } from '../../models/base'; -import config from '../../config'; const router = Router({ mergeParams: true }); const secp256k1 = require('secp256k1'); const bitcoreLib = require('bitcore-lib'); @@ -53,7 +53,7 @@ const authenticate: RequestHandler = async (req: PreAuthRequest, res: Response, return res.status(404).send('Wallet not found'); } Object.assign(req, { wallet }); - if(config.api.wallets.allowUnauthenticatedCalls) { + if(Config.for('api').wallets.allowUnauthenticatedCalls) { return next(); } try { diff --git a/packages/bitcore-node/src/routes/middleware.ts b/packages/bitcore-node/src/routes/middleware.ts index 045eca8a04d..200aabbf6fe 100644 --- a/packages/bitcore-node/src/routes/middleware.ts +++ b/packages/bitcore-node/src/routes/middleware.ts @@ -1,7 +1,7 @@ import logger from '../logger'; import * as express from 'express'; import { RateLimitModel } from '../models/rateLimit'; -import config from '../config'; +import { Config } from "../services/config"; type TimedRequest = { startTime?: Date; @@ -71,7 +71,7 @@ export function RateLimiter(method: string, perSecond: number, perMinute: number return async (req: express.Request, res: express.Response, next: express.NextFunction) => { try { const identifier = req.header('CF-Connecting-IP') || req.socket.remoteAddress || ''; - if (config.api.rateLimiter.whitelist.includes(identifier)) { + if (Config.for('api').rateLimiter.whitelist.includes(identifier)) { return next(); } let [perSecondResult, perMinuteResult, perHourResult] = await RateLimitModel.incrementAndCheck( diff --git a/packages/bitcore-node/src/server.ts b/packages/bitcore-node/src/server.ts index b22ed3ddaa3..5dab5d970e4 100755 --- a/packages/bitcore-node/src/server.ts +++ b/packages/bitcore-node/src/server.ts @@ -1,43 +1,45 @@ -import { P2pService } from './services/p2p'; +import { P2P } from './services/p2p'; import { Storage } from './services/storage'; import { Worker } from './services/worker'; import { Api } from './services/api'; import cluster = require('cluster'); import parseArgv from './utils/parseArgv'; +import { Event } from './services/event'; let args = parseArgv([], ['DEBUG']); -process.on('unhandledRejection', (error) => { - console.error('Unhandled Rejection at:', error.stack || error) +process.on('unhandledRejection', error => { + console.error('Unhandled Rejection at:', error.stack || error); }); const startServices = async () => { - await Storage.start({}); await Worker.start(); - P2pService.startConfiguredChains(); + await P2P.start(); }; -const runMaster = async() => { +const runMaster = async () => { await startServices(); // start the API on master if we are in debug - if(args.DEBUG){ - Api.start(); + if (args.DEBUG) { + await Api.start(); } }; -const runWorker = async() => { +const runWorker = async () => { // don't run any workers when in debug mode - if(!args.DEBUG){ + if (!args.DEBUG) { // Api will automatically start storage if it isn't already running - Api.start(); + await Api.start(); } -} +}; -const start = async() => { - if(cluster.isMaster){ +const start = async () => { + await Storage.start({}); + await Event.start(); + if (cluster.isMaster) { await runMaster(); - } else{ + } else { await runWorker(); } -} +}; start(); diff --git a/packages/bitcore-node/src/services/api.ts b/packages/bitcore-node/src/services/api.ts index b8ab637f580..95990b66c7e 100644 --- a/packages/bitcore-node/src/services/api.ts +++ b/packages/bitcore-node/src/services/api.ts @@ -1,39 +1,59 @@ import * as http from 'http'; -import SocketIO = require('socket.io'); -import mongoose from 'mongoose'; import app from '../routes'; import logger from '../logger'; import config from '../config'; import { LoggifyClass } from '../decorators/Loggify'; -import { Storage } from './storage'; -import { Socket } from './socket'; +import { Storage, StorageService } from './storage'; +import { Socket, SocketService } from './socket'; +import { ConfigService, Config } from './config'; +import { ConfigType } from '../types/Config'; @LoggifyClass export class ApiService { port: number; timeout: number; + configService: ConfigService; + serviceConfig: ConfigType['services']['api']; + storageService: StorageService; + socketService: SocketService; + httpServer: http.Server; - constructor(options) { - const { port, timeout } = options; - - this.port = port || 3000; - this.timeout = timeout || 600000; + constructor({ + port = 3000, + timeout = 600000, + configService = Config, + storageService = Storage, + socketService = Socket + } = {}) { + this.port = port; + this.timeout = timeout; + this.configService = configService; + this.serviceConfig = this.configService.for('api'); + this.storageService = storageService; + this.socketService = socketService; + this.httpServer = new http.Server(app); } - async start() { - if (mongoose.connection.readyState !== 1) { - await Storage.start({}); + async start({ config = Config.current } = {}) { + if (!config.services.api.enabled) { + return; + } + if (!this.storageService.connected) { + await this.storageService.start({}); } - const httpServer = new http.Server(app); - const io = SocketIO(httpServer); - httpServer.listen(this.port, () => { + this.httpServer.timeout = this.timeout; + this.httpServer.listen(this.port, () => { logger.info(`API server started on port ${this.port}`); - Socket.setServer(io); + this.socketService.start({ server: this.httpServer, config }); }); - httpServer.timeout = this.timeout; + return this.httpServer; } - stop() {} + stop() { + return new Promise(resolve => { + this.httpServer.close(resolve); + }); + } } // TOOO: choose a place in the config for the API timeout and include it here diff --git a/packages/bitcore-node/src/services/config.ts b/packages/bitcore-node/src/services/config.ts new file mode 100644 index 00000000000..f58a2ccf585 --- /dev/null +++ b/packages/bitcore-node/src/services/config.ts @@ -0,0 +1,33 @@ +import { ConfigType } from '../types/Config'; +import config from '../config'; + +type RecursivePartial = { [P in keyof T]?: RecursivePartial }; +type ServiceName = keyof ConfigType['services']; + +export class ConfigService { + _config: ConfigType; + + constructor({ _config = config } = {}) { + this._config = _config; + } + + public get current() { + return this._config; + } + + public updateConfig(partialConfig: RecursivePartial) { + const newConfig = Object.assign({}, this.current, partialConfig); + this._config = newConfig; + console.log('Writing', newConfig); + } + + public for(service: T): ConfigType['services'][T] { + return this.current.services[service]; + } + + public isEnabled(service: ServiceName) { + return this.current.services[service].enabled; + } +} + +export const Config = new ConfigService(); diff --git a/packages/bitcore-node/src/services/event.ts b/packages/bitcore-node/src/services/event.ts index a756b52c8be..c2a2be9af27 100644 --- a/packages/bitcore-node/src/services/event.ts +++ b/packages/bitcore-node/src/services/event.ts @@ -1,30 +1,56 @@ +import logger from '../logger'; +import { StorageService } from './storage'; import { LoggifyClass } from '../decorators/Loggify'; -import { EventModel, IEvent } from '../models/events'; +import { EventModel, IEvent, EventSchema } from '../models/events'; import { PassThrough } from 'stream'; import { Storage } from './storage'; +import { Config, ConfigService } from './config'; +import { ConfigType } from '../types/Config'; @LoggifyClass export class EventService { txStream = new PassThrough({ objectMode: true }); blockStream = new PassThrough({ objectMode: true }); addressCoinStream = new PassThrough({ objectMode: true }); + storageService: StorageService; + configService: ConfigService; + serviceConfig: ConfigType['services']['event']; + eventModel: EventSchema; + stopped = false; - constructor() { + constructor({ storageService = Storage, eventModel = EventModel, configService = Config } = {}) { + this.storageService = storageService; + this.configService = configService; + this.eventModel = eventModel; this.signalTx = this.signalTx.bind(this); this.signalBlock = this.signalBlock.bind(this); this.signalAddressCoin = this.signalAddressCoin.bind(this); - Storage.connection.on('CONNECTED', () => { + this.serviceConfig = this.configService.for('event'); + } + + start(config: ConfigType = this.configService.current) { + if (!config.services.event.enabled) { + return; + } + logger.info('Starting Event Service'); + this.stopped = false; + this.storageService.connection.on('CONNECTED', () => { this.wireup(); }); } + stop() { + logger.info('Stopping Event Service'); + this.stopped = true; + } + async wireup() { let lastBlockUpdate = new Date(); let lastTxUpdate = new Date(); let lastAddressTxUpdate = new Date(); const retryTxCursor = async () => { - const txCursor = EventModel.getTxTail(lastTxUpdate); + const txCursor = this.eventModel.getTxTail(lastTxUpdate); while (await txCursor.hasNext()) { const txEvent = await txCursor.next(); if (txEvent) { @@ -33,12 +59,14 @@ export class EventService { lastTxUpdate = new Date(); } } - setTimeout(retryTxCursor, 5000); + if (!this.stopped) { + setTimeout(retryTxCursor, 5000); + } }; retryTxCursor(); const retryBlockCursor = async () => { - const blockCursor = EventModel.getBlockTail(lastBlockUpdate); + const blockCursor = this.eventModel.getBlockTail(lastBlockUpdate); while (await blockCursor.hasNext()) { const blockEvent = await blockCursor.next(); if (blockEvent) { @@ -47,12 +75,14 @@ export class EventService { lastBlockUpdate = new Date(); } } - setTimeout(retryBlockCursor, 5000); + if (!this.stopped) { + setTimeout(retryBlockCursor, 5000); + } }; retryBlockCursor(); const retryAddressTxCursor = async () => { - const addressTxCursor = EventModel.getCoinTail(lastAddressTxUpdate); + const addressTxCursor = this.eventModel.getCoinTail(lastAddressTxUpdate); while (await addressTxCursor.hasNext()) { const addressTx = await addressTxCursor.next(); if (addressTx) { @@ -61,21 +91,23 @@ export class EventService { lastAddressTxUpdate = new Date(); } } - setTimeout(retryAddressTxCursor, 5000); + if (!this.stopped) { + setTimeout(retryAddressTxCursor, 5000); + } }; retryAddressTxCursor(); } async signalBlock(block: IEvent.BlockEvent) { - await EventModel.signalBlock(block); + await this.eventModel.signalBlock(block); } async signalTx(tx: IEvent.TxEvent) { - await EventModel.signalTx(tx); + await this.eventModel.signalTx(tx); } async signalAddressCoin(payload: IEvent.CoinEvent) { - await EventModel.signalAddressCoin(payload); + await this.eventModel.signalAddressCoin(payload); } } diff --git a/packages/bitcore-node/src/services/p2p.ts b/packages/bitcore-node/src/services/p2p.ts index e4fc7e83257..d5b3d0b52a6 100644 --- a/packages/bitcore-node/src/services/p2p.ts +++ b/packages/bitcore-node/src/services/p2p.ts @@ -1,16 +1,62 @@ -import config from '../config'; import logger from '../logger'; import { EventEmitter } from 'events'; -import { BlockModel } from '../models/block'; +import { BlockModel, BlockSchema } from '../models/block'; import { ChainStateProvider } from '../providers/chain-state'; import { TransactionModel } from '../models/transaction'; import { Bitcoin } from '../types/namespaces/Bitcoin'; import { StateModel } from '../models/state'; import { SpentHeightIndicators } from '../types/Coin'; +import { Config, ConfigService } from './config'; +import { ConfigType } from '../types/Config'; const Chain = require('../chain'); const LRU = require('lru-cache'); -export class P2pService { +export class P2pManager { + workers = new Array(); + + private configService: ConfigService; + + constructor({ configService = Config } = {}) { + this.configService = configService; + } + + async stop() { + logger.info('Stopping P2P Manager'); + for (const worker of this.workers) { + await worker.stop(); + } + } + + async start({ config = this.configService.current, blockModel = BlockModel } = {}) { + if (!config.services.p2p.enabled) { + return; + } + logger.info('Starting P2P Manager'); + const p2pWorkers = new Array(); + for (let chain of Object.keys(config.chains)) { + for (let network of Object.keys(config.chains[chain])) { + const chainConfig = config.chains[chain][network]; + if (chainConfig.chainSource && chainConfig.chainSource !== 'p2p') { + continue; + } + const p2pWorker = new P2pWorker({ + chain, + network, + chainConfig, + blockModel + }); + p2pWorkers.push(p2pWorker); + try { + p2pWorker.start(config); + } catch (e) { + logger.error('P2P Worker died with', e); + } + } + } + } +} + +export class P2pWorker { private chain: string; private network: string; private bitcoreLib: any; @@ -20,10 +66,14 @@ export class P2pService { private syncing: boolean; private messages: any; private pool: any; + private connectInterval?: NodeJS.Timer; private invCache: any; private initialSyncComplete: boolean; - constructor(params) { - const { chain, network, chainConfig } = params; + private stopped: boolean; + private blockModel: BlockSchema; + constructor({ chain, network, chainConfig, blockModel = BlockModel }) { + this.blockModel = blockModel; + this.stopped = true; this.chain = chain; this.network = network; this.bitcoreLib = Chain[this.chain].lib; @@ -130,25 +180,17 @@ export class P2pService { async connect() { this.pool.connect(); - setInterval(this.pool.connect.bind(this.pool), 5000); + this.connectInterval = setInterval(this.pool.connect.bind(this.pool), 5000); return new Promise(resolve => { this.pool.once('peerready', () => resolve()); }); } - static startConfiguredChains() { - for (let chain of Object.keys(config.chains)) { - for (let network of Object.keys(config.chains[chain])) { - const chainConfig = config.chains[chain][network]; - if (chainConfig.chainSource && chainConfig.chainSource !== 'p2p') { - continue; - } - new P2pService({ - chain, - network, - chainConfig - }).start(); - } + async disconnect() { + this.pool.removeAllListeners(); + this.pool.disconnect(); + if (this.connectInterval) { + clearInterval(this.connectInterval); } } @@ -201,7 +243,7 @@ export class P2pService { async processBlock(block): Promise { return new Promise(async (resolve, reject) => { try { - await BlockModel.addBlock({ + await this.blockModel.addBlock({ chain: this.chain, network: this.network, forkHeight: this.chainConfig.forkHeight, @@ -237,7 +279,7 @@ export class P2pService { } async sync() { - if (this.syncing) { + if (this.syncing || this.stopped) { return; } this.syncing = true; @@ -271,6 +313,9 @@ export class P2pService { logger.info(`Syncing ${headers.length} blocks for ${chain} ${network}`); for (const header of headers) { try { + if (!this.stopped) { + throw new Error('Stopped'); + } const block = await this.getBlock(header.hash); await this.processBlock(block); currentHeight++; @@ -285,7 +330,9 @@ export class P2pService { } catch (err) { logger.error(`Error syncing ${chain} ${network}`, err); this.syncing = false; - return this.sync(); + if (!this.stopped) { + return this.sync(); + } } } headers = await getHeaders(); @@ -300,10 +347,22 @@ export class P2pService { return true; } - async start() { + async stop() { + logger.debug(`Stopping worker for chain ${this.chain}`); + this.stopped = true; + await this.disconnect(); + } + + async start(config: ConfigType) { + if (!config.services.p2p.enabled) { + return; + } + this.stopped = false; logger.debug(`Started worker for chain ${this.chain}`); this.setupListeners(); await this.connect(); this.sync(); } } + +export const P2P = new P2pManager(); diff --git a/packages/bitcore-node/src/services/socket.ts b/packages/bitcore-node/src/services/socket.ts index 4ab829bf15f..6bf35630d1b 100644 --- a/packages/bitcore-node/src/services/socket.ts +++ b/packages/bitcore-node/src/services/socket.ts @@ -1,8 +1,12 @@ +import logger from '../logger'; import SocketIO = require('socket.io'); +import * as http from 'http'; import { LoggifyClass } from '../decorators/Loggify'; -import { EventModel, IEvent } from '../models/events'; -import { Event } from './event'; +import { EventModel, IEvent, EventSchema } from '../models/events'; +import { Event, EventService } from './event'; import { ObjectID } from 'mongodb'; +import { Config, ConfigService } from './config'; +import { ConfigType } from '../types/Config'; function SanitizeWallet(x: { wallets: ObjectID[] }) { const sanitized = Object.assign({}, x, { wallets: undefined }); @@ -14,18 +18,32 @@ function SanitizeWallet(x: { wallets: ObjectID[] }) { @LoggifyClass export class SocketService { + httpServer?: http.Server; io?: SocketIO.Server; id: number = Math.random(); + configService: ConfigService; + serviceConfig: ConfigType['services']['socket']; + eventService: EventService; + eventModel: EventSchema; - constructor() { - this.setServer = this.setServer.bind(this); + constructor({ eventService = Event, eventModel = EventModel, configService = Config } = {}) { + this.eventService = eventService; + this.configService = configService; + this.serviceConfig = this.configService.for('socket'); + this.eventModel = eventModel; + this.start = this.start.bind(this); this.signalTx = this.signalTx.bind(this); this.signalBlock = this.signalBlock.bind(this); this.signalAddressCoin = this.signalAddressCoin.bind(this); } - setServer(io: SocketIO.Server) { - this.io = io; + start({ server, config = this.configService.current }: { server: http.Server; config: ConfigType }) { + if (!config.services.socket.enabled) { + return; + } + logger.info('Starting Socket Service'); + this.httpServer = server; + this.io = SocketIO(server); this.io.sockets.on('connection', socket => { socket.on('room', room => { socket.join(room); @@ -34,8 +52,19 @@ export class SocketService { this.wireup(); } + stop() { + logger.info('Stopping Socket Service'); + return new Promise(resolve => { + if (this.io) { + this.io.close(resolve); + } else { + resolve(); + } + }); + } + async wireup() { - Event.txStream.on('data', (tx: IEvent.TxEvent) => { + this.eventService.txStream.on('data', (tx: IEvent.TxEvent) => { if (this.io) { const { chain, network } = tx; const sanitizedTx = SanitizeWallet(tx); @@ -43,14 +72,14 @@ export class SocketService { } }); - Event.blockStream.on('data', (block: IEvent.BlockEvent) => { + this.eventService.blockStream.on('data', (block: IEvent.BlockEvent) => { if (this.io) { const { chain, network } = block; this.io.sockets.in(`/${chain}/${network}/inv`).emit('block', block); } }); - Event.addressCoinStream.on('data', (addressCoin: IEvent.CoinEvent) => { + this.eventService.addressCoinStream.on('data', (addressCoin: IEvent.CoinEvent) => { if (this.io) { const { coin, address } = addressCoin; const { chain, network } = coin; diff --git a/packages/bitcore-node/src/services/storage.ts b/packages/bitcore-node/src/services/storage.ts index 2458585d0f2..9d7b41108a2 100644 --- a/packages/bitcore-node/src/services/storage.ts +++ b/packages/bitcore-node/src/services/storage.ts @@ -2,13 +2,14 @@ import { EventEmitter } from 'events'; import { Request, Response } from 'express'; import { TransformableModel } from '../types/TransformableModel'; import logger from '../logger'; -import config from '../config'; import { LoggifyClass } from '../decorators/Loggify'; import { ObjectID } from 'mongodb'; import { MongoClient, Db, Cursor } from 'mongodb'; import { MongoBound } from '../models/base'; import '../models'; import { StreamingFindOptions } from '../types/Query'; +import { ConfigType } from '../types/Config'; +import { Config, ConfigService } from './config'; export { StreamingFindOptions }; @@ -18,10 +19,15 @@ export class StorageService { db?: Db; connected: boolean = false; connection = new EventEmitter(); + configService: ConfigService; - start(args: any): Promise { + constructor({ configService = Config } = {}) { + this.configService = configService; + } + + start(args: Partial = {}): Promise { return new Promise((resolve, reject) => { - let options = Object.assign({}, config, args); + let options = Object.assign({}, this.configService.current, args); let { dbName, dbHost, dbPort } = options; const connectUrl = `mongodb://${dbHost}:${dbPort}/${dbName}?socketTimeoutMS=3600000&noDelay=true`; let attemptConnect = async () => { @@ -29,7 +35,7 @@ export class StorageService { connectUrl, { keepAlive: true, - poolSize: config.maxPoolSize, + poolSize: options.maxPoolSize, useNewUrlParser: true } ); @@ -174,9 +180,12 @@ export class StorageService { ) { const { query, options } = this.getFindOptions(model, originalOptions); const finalQuery = Object.assign({}, originalQuery, query); - let cursor = model.collection.find(finalQuery, options).addCursorFlag('noCursorTimeout', true).stream({ - transform: transform || model._apiTransform - }); + let cursor = model.collection + .find(finalQuery, options) + .addCursorFlag('noCursorTimeout', true) + .stream({ + transform: transform || model._apiTransform + }); if (options.sort) { cursor = cursor.sort(options.sort); } diff --git a/packages/bitcore-node/src/types/Config.d.ts b/packages/bitcore-node/src/types/Config.d.ts index 9d63ffdb079..8971f5334b1 100644 --- a/packages/bitcore-node/src/types/Config.d.ts +++ b/packages/bitcore-node/src/types/Config.d.ts @@ -1,4 +1,4 @@ -export default interface Config { +export interface ConfigType { maxPoolSize: number; port: number; dbHost: string; @@ -7,15 +7,30 @@ export default interface Config { numWorkers: number; chains: { - [currency: string]: any; + [currency: string]: { [network: string]: any }; }; - api: { - rateLimiter: { - whitelist: [string]; - }, - wallets: { - allowCreationBeforeCompleteSync?: boolean; - allowUnauthenticatedCalls?: boolean; + services: { + api: { + enabled: boolean; + rateLimiter: { + whitelist: [string]; + }; + wallets: { + allowCreationBeforeCompleteSync?: boolean; + allowUnauthenticatedCalls?: boolean; + }; + }; + event: { + enabled: boolean; + }; + p2p: { + enabled: boolean; + }; + socket: { + enabled: boolean; + }; + storage: { + enabled: boolean; }; }; } From 4ee114f4729e26ab6501ff8a7399b57443b1d4b4 Mon Sep 17 00:00:00 2001 From: Micah Riggan Date: Wed, 26 Dec 2018 17:42:39 -0500 Subject: [PATCH 2/9] config get function --- packages/bitcore-node/src/models/transaction.ts | 6 +++--- .../src/providers/chain-state/internal/internal.ts | 2 +- packages/bitcore-node/src/services/api.ts | 7 ++----- packages/bitcore-node/src/services/config.ts | 9 ++++----- packages/bitcore-node/src/services/event.ts | 7 ++----- packages/bitcore-node/src/services/p2p.ts | 12 ++++++------ packages/bitcore-node/src/services/socket.ts | 2 +- packages/bitcore-node/src/services/storage.ts | 2 +- 8 files changed, 20 insertions(+), 27 deletions(-) diff --git a/packages/bitcore-node/src/models/transaction.ts b/packages/bitcore-node/src/models/transaction.ts index a8505ad7faa..7093d81773c 100644 --- a/packages/bitcore-node/src/models/transaction.ts +++ b/packages/bitcore-node/src/models/transaction.ts @@ -82,7 +82,7 @@ export class TransactionSchema extends BaseModel { logger.debug('Minting Coins', mintOps.length); if (mintOps.length) { await Promise.all( - partition(mintOps, mintOps.length / Config.current.maxPoolSize).map(mintBatch => + partition(mintOps, mintOps.length / Config.get().maxPoolSize).map(mintBatch => CoinModel.collection.bulkWrite(mintBatch, { ordered: false }) ) ); @@ -91,7 +91,7 @@ export class TransactionSchema extends BaseModel { logger.debug('Spending Coins', spendOps.length); if (spendOps.length) { await Promise.all( - partition(spendOps, spendOps.length / Config.current.maxPoolSize).map(spendBatch => + partition(spendOps, spendOps.length / Config.get().maxPoolSize).map(spendBatch => CoinModel.collection.bulkWrite(spendBatch, { ordered: false }) ) ); @@ -101,7 +101,7 @@ export class TransactionSchema extends BaseModel { const txOps = await this.addTransactions({ ...params, mintOps }); logger.debug('Writing Transactions', txOps.length); await Promise.all( - partition(txOps, txOps.length / Config.current.maxPoolSize).map(txBatch => + partition(txOps, txOps.length / Config.get().maxPoolSize).map(txBatch => this.collection.bulkWrite(txBatch, { ordered: false }) ) ); diff --git a/packages/bitcore-node/src/providers/chain-state/internal/internal.ts b/packages/bitcore-node/src/providers/chain-state/internal/internal.ts index cf415df0378..37a76791adf 100644 --- a/packages/bitcore-node/src/providers/chain-state/internal/internal.ts +++ b/packages/bitcore-node/src/providers/chain-state/internal/internal.ts @@ -27,7 +27,7 @@ export class InternalStateProvider implements CSP.IChainStateService { } getRPC(chain: string, network: string) { - const RPC_PEER = Config.current.chains[chain][network].rpc; + const RPC_PEER = Config.get().chains[chain][network].rpc; if (!RPC_PEER) { throw new Error(`RPC not configured for ${chain} ${network}`); } diff --git a/packages/bitcore-node/src/services/api.ts b/packages/bitcore-node/src/services/api.ts index 95990b66c7e..67d25c220b8 100644 --- a/packages/bitcore-node/src/services/api.ts +++ b/packages/bitcore-node/src/services/api.ts @@ -6,14 +6,12 @@ import { LoggifyClass } from '../decorators/Loggify'; import { Storage, StorageService } from './storage'; import { Socket, SocketService } from './socket'; import { ConfigService, Config } from './config'; -import { ConfigType } from '../types/Config'; @LoggifyClass export class ApiService { port: number; timeout: number; configService: ConfigService; - serviceConfig: ConfigType['services']['api']; storageService: StorageService; socketService: SocketService; httpServer: http.Server; @@ -28,14 +26,13 @@ export class ApiService { this.port = port; this.timeout = timeout; this.configService = configService; - this.serviceConfig = this.configService.for('api'); this.storageService = storageService; this.socketService = socketService; this.httpServer = new http.Server(app); } - async start({ config = Config.current } = {}) { - if (!config.services.api.enabled) { + async start() { + if (!this.configService.isEnabled('api')) { return; } if (!this.storageService.connected) { diff --git a/packages/bitcore-node/src/services/config.ts b/packages/bitcore-node/src/services/config.ts index f58a2ccf585..f9d652d306b 100644 --- a/packages/bitcore-node/src/services/config.ts +++ b/packages/bitcore-node/src/services/config.ts @@ -11,22 +11,21 @@ export class ConfigService { this._config = _config; } - public get current() { + public get() { return this._config; } public updateConfig(partialConfig: RecursivePartial) { - const newConfig = Object.assign({}, this.current, partialConfig); + const newConfig = Object.assign({}, this.get(), partialConfig); this._config = newConfig; - console.log('Writing', newConfig); } public for(service: T): ConfigType['services'][T] { - return this.current.services[service]; + return this.get().services[service]; } public isEnabled(service: ServiceName) { - return this.current.services[service].enabled; + return this.get().services[service].enabled; } } diff --git a/packages/bitcore-node/src/services/event.ts b/packages/bitcore-node/src/services/event.ts index c2a2be9af27..79dd078c534 100644 --- a/packages/bitcore-node/src/services/event.ts +++ b/packages/bitcore-node/src/services/event.ts @@ -5,7 +5,6 @@ import { EventModel, IEvent, EventSchema } from '../models/events'; import { PassThrough } from 'stream'; import { Storage } from './storage'; import { Config, ConfigService } from './config'; -import { ConfigType } from '../types/Config'; @LoggifyClass export class EventService { @@ -14,7 +13,6 @@ export class EventService { addressCoinStream = new PassThrough({ objectMode: true }); storageService: StorageService; configService: ConfigService; - serviceConfig: ConfigType['services']['event']; eventModel: EventSchema; stopped = false; @@ -25,11 +23,10 @@ export class EventService { this.signalTx = this.signalTx.bind(this); this.signalBlock = this.signalBlock.bind(this); this.signalAddressCoin = this.signalAddressCoin.bind(this); - this.serviceConfig = this.configService.for('event'); } - start(config: ConfigType = this.configService.current) { - if (!config.services.event.enabled) { + start() { + if (!this.configService.isEnabled('event')) { return; } logger.info('Starting Event Service'); diff --git a/packages/bitcore-node/src/services/p2p.ts b/packages/bitcore-node/src/services/p2p.ts index d5b3d0b52a6..98b6fc1b59a 100644 --- a/packages/bitcore-node/src/services/p2p.ts +++ b/packages/bitcore-node/src/services/p2p.ts @@ -27,15 +27,15 @@ export class P2pManager { } } - async start({ config = this.configService.current, blockModel = BlockModel } = {}) { - if (!config.services.p2p.enabled) { + async start({ blockModel = BlockModel } = {}) { + if (!this.configService.isEnabled('p2p')) { return; } logger.info('Starting P2P Manager'); const p2pWorkers = new Array(); - for (let chain of Object.keys(config.chains)) { - for (let network of Object.keys(config.chains[chain])) { - const chainConfig = config.chains[chain][network]; + for (let chain of Object.keys(Config.get().chains)) { + for (let network of Object.keys(Config.get().chains[chain])) { + const chainConfig = Config.get().chains[chain][network]; if (chainConfig.chainSource && chainConfig.chainSource !== 'p2p') { continue; } @@ -47,7 +47,7 @@ export class P2pManager { }); p2pWorkers.push(p2pWorker); try { - p2pWorker.start(config); + p2pWorker.start(Config.get()); } catch (e) { logger.error('P2P Worker died with', e); } diff --git a/packages/bitcore-node/src/services/socket.ts b/packages/bitcore-node/src/services/socket.ts index 6bf35630d1b..a6e95a91c77 100644 --- a/packages/bitcore-node/src/services/socket.ts +++ b/packages/bitcore-node/src/services/socket.ts @@ -37,7 +37,7 @@ export class SocketService { this.signalAddressCoin = this.signalAddressCoin.bind(this); } - start({ server, config = this.configService.current }: { server: http.Server; config: ConfigType }) { + start({ server, config = this.configService.get() }: { server: http.Server; config: ConfigType }) { if (!config.services.socket.enabled) { return; } diff --git a/packages/bitcore-node/src/services/storage.ts b/packages/bitcore-node/src/services/storage.ts index 9d7b41108a2..48a0980a4e5 100644 --- a/packages/bitcore-node/src/services/storage.ts +++ b/packages/bitcore-node/src/services/storage.ts @@ -27,7 +27,7 @@ export class StorageService { start(args: Partial = {}): Promise { return new Promise((resolve, reject) => { - let options = Object.assign({}, this.configService.current, args); + let options = Object.assign({}, this.configService.get(), args); let { dbName, dbHost, dbPort } = options; const connectUrl = `mongodb://${dbHost}:${dbPort}/${dbName}?socketTimeoutMS=3600000&noDelay=true`; let attemptConnect = async () => { From 920709ebdffc86b5da0b22a9916bf2276275a6f7 Mon Sep 17 00:00:00 2001 From: Micah Riggan Date: Wed, 26 Dec 2018 17:46:26 -0500 Subject: [PATCH 3/9] simplifying isEnabled --- packages/bitcore-node/src/services/config.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/bitcore-node/src/services/config.ts b/packages/bitcore-node/src/services/config.ts index f9d652d306b..996f102ffb5 100644 --- a/packages/bitcore-node/src/services/config.ts +++ b/packages/bitcore-node/src/services/config.ts @@ -25,7 +25,7 @@ export class ConfigService { } public isEnabled(service: ServiceName) { - return this.get().services[service].enabled; + return this.for(service).enabled; } } From 6c41bfa9f825ec624f0b93aa38314208ce80fe47 Mon Sep 17 00:00:00 2001 From: Micah Riggan Date: Thu, 27 Dec 2018 10:08:29 -0500 Subject: [PATCH 4/9] Removing stopped variable --- packages/bitcore-node/src/services/p2p.ts | 13 ++----------- 1 file changed, 2 insertions(+), 11 deletions(-) diff --git a/packages/bitcore-node/src/services/p2p.ts b/packages/bitcore-node/src/services/p2p.ts index 98b6fc1b59a..7e971595387 100644 --- a/packages/bitcore-node/src/services/p2p.ts +++ b/packages/bitcore-node/src/services/p2p.ts @@ -69,11 +69,9 @@ export class P2pWorker { private connectInterval?: NodeJS.Timer; private invCache: any; private initialSyncComplete: boolean; - private stopped: boolean; private blockModel: BlockSchema; constructor({ chain, network, chainConfig, blockModel = BlockModel }) { this.blockModel = blockModel; - this.stopped = true; this.chain = chain; this.network = network; this.bitcoreLib = Chain[this.chain].lib; @@ -279,7 +277,7 @@ export class P2pWorker { } async sync() { - if (this.syncing || this.stopped) { + if (this.syncing) { return; } this.syncing = true; @@ -313,9 +311,6 @@ export class P2pWorker { logger.info(`Syncing ${headers.length} blocks for ${chain} ${network}`); for (const header of headers) { try { - if (!this.stopped) { - throw new Error('Stopped'); - } const block = await this.getBlock(header.hash); await this.processBlock(block); currentHeight++; @@ -330,9 +325,7 @@ export class P2pWorker { } catch (err) { logger.error(`Error syncing ${chain} ${network}`, err); this.syncing = false; - if (!this.stopped) { - return this.sync(); - } + return this.sync(); } } headers = await getHeaders(); @@ -349,7 +342,6 @@ export class P2pWorker { async stop() { logger.debug(`Stopping worker for chain ${this.chain}`); - this.stopped = true; await this.disconnect(); } @@ -357,7 +349,6 @@ export class P2pWorker { if (!config.services.p2p.enabled) { return; } - this.stopped = false; logger.debug(`Started worker for chain ${this.chain}`); this.setupListeners(); await this.connect(); From e64710fade91d1f1958168aa679470206c267a5f Mon Sep 17 00:00:00 2001 From: Micah Riggan Date: Thu, 27 Dec 2018 10:40:33 -0500 Subject: [PATCH 5/9] Adding utility for config --- packages/bitcore-node/src/services/config.ts | 23 +++++++++++++ packages/bitcore-node/src/services/p2p.ts | 35 ++++++++++---------- 2 files changed, 40 insertions(+), 18 deletions(-) diff --git a/packages/bitcore-node/src/services/config.ts b/packages/bitcore-node/src/services/config.ts index 996f102ffb5..24756c50e71 100644 --- a/packages/bitcore-node/src/services/config.ts +++ b/packages/bitcore-node/src/services/config.ts @@ -1,5 +1,6 @@ import { ConfigType } from '../types/Config'; import config from '../config'; +import { ChainNetwork } from '../types/ChainNetwork'; type RecursivePartial = { [P in keyof T]?: RecursivePartial }; type ServiceName = keyof ConfigType['services']; @@ -20,6 +21,28 @@ export class ConfigService { this._config = newConfig; } + public chains() { + return Object.keys(this.get().chains); + } + + public networksFor(chain: keyof ConfigType['chains']) { + return Object.keys(this.get().chains[chain]); + } + + public chainNetworks(): Array { + const chainNetworks = new Array(); + for (let chain of this.chains()) { + for (let network of this.networksFor(chain)) { + chainNetworks.push({ chain, network }); + } + } + return chainNetworks; + } + + public chainConfig({chain, network}: ChainNetwork) { + return this.get().chains[chain][network]; + } + public for(service: T): ConfigType['services'][T] { return this.get().services[service]; } diff --git a/packages/bitcore-node/src/services/p2p.ts b/packages/bitcore-node/src/services/p2p.ts index 7e971595387..ccaabe967d4 100644 --- a/packages/bitcore-node/src/services/p2p.ts +++ b/packages/bitcore-node/src/services/p2p.ts @@ -33,24 +33,23 @@ export class P2pManager { } logger.info('Starting P2P Manager'); const p2pWorkers = new Array(); - for (let chain of Object.keys(Config.get().chains)) { - for (let network of Object.keys(Config.get().chains[chain])) { - const chainConfig = Config.get().chains[chain][network]; - if (chainConfig.chainSource && chainConfig.chainSource !== 'p2p') { - continue; - } - const p2pWorker = new P2pWorker({ - chain, - network, - chainConfig, - blockModel - }); - p2pWorkers.push(p2pWorker); - try { - p2pWorker.start(Config.get()); - } catch (e) { - logger.error('P2P Worker died with', e); - } + for (let chainNetwork of Config.chainNetworks()) { + const chainConfig = Config.chainConfig(chainNetwork); + if (chainConfig.chainSource && chainConfig.chainSource !== 'p2p') { + continue; + } + const { chain, network } = chainConfig; + const p2pWorker = new P2pWorker({ + chain, + network, + chainConfig, + blockModel + }); + p2pWorkers.push(p2pWorker); + try { + p2pWorker.start(Config.get()); + } catch (e) { + logger.error('P2P Worker died with', e); } } } From 672a87f27fee2d4a5576400862ed667cd67db318 Mon Sep 17 00:00:00 2001 From: Micah Riggan Date: Thu, 27 Dec 2018 11:11:44 -0500 Subject: [PATCH 6/9] Renaming Model singletons to XStorage and XSchema to XModel --- packages/bitcore-node/src/models/block.ts | 22 +++--- packages/bitcore-node/src/models/coin.ts | 4 +- packages/bitcore-node/src/models/events.ts | 4 +- packages/bitcore-node/src/models/rateLimit.ts | 4 +- packages/bitcore-node/src/models/state.ts | 4 +- .../bitcore-node/src/models/transaction.ts | 24 +++--- packages/bitcore-node/src/models/wallet.ts | 6 +- .../bitcore-node/src/models/walletAddress.ts | 18 ++--- .../src/providers/chain-state/eth/eth.ts | 4 +- .../chain-state/internal/internal.ts | 74 +++++++++---------- .../chain-state/internal/transforms.ts | 8 +- .../bitcore-node/src/routes/middleware.ts | 4 +- packages/bitcore-node/src/server.ts | 14 ++-- packages/bitcore-node/src/services/event.ts | 6 +- packages/bitcore-node/src/services/p2p.ts | 18 ++--- packages/bitcore-node/src/services/socket.ts | 12 +-- .../bitcore-node/test/benchmark/benchmark.ts | 4 +- .../test/benchmark/wallet-benchmark.ts | 4 +- packages/bitcore-node/test/helpers/index.ts | 16 ++-- .../integration/models/block.integration.ts | 72 +++++++++--------- .../test/unit/models/block.unit.ts | 74 +++++++++---------- .../test/unit/models/coin.unit.ts | 6 +- .../test/unit/models/wallet.unit.ts | 6 +- .../test/unit/models/walletAddress.unit.ts | 6 +- packages/bitcore-node/test/util/verify.ts | 22 +++--- 25 files changed, 217 insertions(+), 219 deletions(-) diff --git a/packages/bitcore-node/src/models/block.ts b/packages/bitcore-node/src/models/block.ts index 05ea099a19a..6e374488fc7 100644 --- a/packages/bitcore-node/src/models/block.ts +++ b/packages/bitcore-node/src/models/block.ts @@ -1,6 +1,6 @@ import { valueOrDefault } from '../utils/check'; -import { CoinModel } from './coin'; -import { TransactionModel } from './transaction'; +import { CoinStorage } from './coin'; +import { TransactionStorage } from './transaction'; import { TransformOptions } from '../types/TransformOptions'; import { LoggifyClass } from '../decorators/Loggify'; import { Bitcoin } from '../types/namespaces/Bitcoin'; @@ -8,7 +8,7 @@ import { BaseModel, MongoBound } from './base'; import logger from '../logger'; import { IBlock } from '../types/Block'; import { SpentHeightIndicators } from '../types/Coin'; -import { EventModel } from './events'; +import { EventStorage } from './events'; import config from '../config'; import { Event } from '../services/event'; import { StorageService } from "../services/storage"; @@ -16,7 +16,7 @@ import { StorageService } from "../services/storage"; export { IBlock }; @LoggifyClass -export class BlockSchema extends BaseModel { +export class BlockModel extends BaseModel { constructor(storage?: StorageService) { super('blocks', storage); } @@ -126,7 +126,7 @@ export class BlockSchema extends BaseModel { logger.debug('Updating previous block.nextBlockHash ', header.hash); } - await TransactionModel.batchImport({ + await TransactionStorage.batchImport({ txs: block.transactions, blockHash: header.hash, blockTime: new Date(blockTime), @@ -140,7 +140,7 @@ export class BlockSchema extends BaseModel { }); if (initialSyncComplete) { - EventModel.signalBlock(convertedBlock); + EventStorage.signalBlock(convertedBlock); } return this.collection.updateOne({ hash: header.hash, chain, network }, { $set: { processed: true } }); @@ -153,7 +153,7 @@ export class BlockSchema extends BaseModel { } getLocalTip({ chain, network }) { - return BlockModel.collection.findOne({ chain, network, processed: true }, { sort: { height: -1 } }); + return BlockStorage.collection.findOne({ chain, network, processed: true }, { sort: { height: -1 } }); } async handleReorg(params: { header?: Bitcoin.Block.HeaderObj; chain: string; network: string }): Promise { @@ -176,12 +176,12 @@ export class BlockSchema extends BaseModel { logger.info(`Resetting tip to ${localTip.height}`, { chain, network }); const reorgOps = [ this.collection.deleteMany({ chain, network, height: { $gte: localTip.height } }), - TransactionModel.collection.deleteMany({ chain, network, blockHeight: { $gte: localTip.height } }), - CoinModel.collection.deleteMany({ chain, network, mintHeight: { $gte: localTip.height } }) + TransactionStorage.collection.deleteMany({ chain, network, blockHeight: { $gte: localTip.height } }), + CoinStorage.collection.deleteMany({ chain, network, mintHeight: { $gte: localTip.height } }) ]; await Promise.all(reorgOps); - await CoinModel.collection.updateMany( + await CoinStorage.collection.updateMany( { chain, network, spentHeight: { $gte: localTip.height } }, { $set: { spentTxid: null, spentHeight: SpentHeightIndicators.pending } } ); @@ -228,4 +228,4 @@ export class BlockSchema extends BaseModel { } } -export let BlockModel = new BlockSchema(); +export let BlockStorage = new BlockModel(); diff --git a/packages/bitcore-node/src/models/coin.ts b/packages/bitcore-node/src/models/coin.ts index 3c9db75b33b..82d3176c66b 100644 --- a/packages/bitcore-node/src/models/coin.ts +++ b/packages/bitcore-node/src/models/coin.ts @@ -22,7 +22,7 @@ export type ICoin = { }; @LoggifyClass -class CoinSchema extends BaseModel { +class CoinModel extends BaseModel { constructor(storage?: StorageService) { super('coins', storage); } @@ -167,4 +167,4 @@ class CoinSchema extends BaseModel { return JSON.stringify(transform); } } -export let CoinModel = new CoinSchema(); +export let CoinStorage = new CoinModel(); diff --git a/packages/bitcore-node/src/models/events.ts b/packages/bitcore-node/src/models/events.ts index 937b9bc9837..d79bed67731 100644 --- a/packages/bitcore-node/src/models/events.ts +++ b/packages/bitcore-node/src/models/events.ts @@ -14,7 +14,7 @@ interface IEvent { type: 'block' | 'tx' | 'coin'; emitTime: Date; } -export class EventSchema extends BaseModel { +export class EventModel extends BaseModel { constructor(storage?: StorageService) { super('events', storage); } @@ -54,4 +54,4 @@ export class EventSchema extends BaseModel { return this.collection.find({ type: 'coin', emitTime: { $gte: lastSeen } }).addCursorFlag('noCursorTimeout', true); } } -export const EventModel = new EventSchema(); +export const EventStorage = new EventModel(); diff --git a/packages/bitcore-node/src/models/rateLimit.ts b/packages/bitcore-node/src/models/rateLimit.ts index 3d3051712c3..6ec018338ac 100644 --- a/packages/bitcore-node/src/models/rateLimit.ts +++ b/packages/bitcore-node/src/models/rateLimit.ts @@ -12,7 +12,7 @@ export type IRateLimit = { expireAt?: Date; }; -export class RateLimitSchema extends BaseModel { +export class RateLimitModel extends BaseModel { constructor(storage?: StorageService) { super('ratelimits', storage); } @@ -53,4 +53,4 @@ export class RateLimitSchema extends BaseModel { } } -export let RateLimitModel = new RateLimitSchema(); +export let RateLimitStorage = new RateLimitModel(); diff --git a/packages/bitcore-node/src/models/state.ts b/packages/bitcore-node/src/models/state.ts index 9cc1e82177e..3175e265d74 100644 --- a/packages/bitcore-node/src/models/state.ts +++ b/packages/bitcore-node/src/models/state.ts @@ -7,7 +7,7 @@ export type IState = { initialSyncComplete: any; }; -export class StateSchema extends BaseModel { +export class StateModel extends BaseModel { constructor(storage?: StorageService) { super('state', storage); } @@ -16,4 +16,4 @@ export class StateSchema extends BaseModel { onConnect() {} } -export let StateModel = new StateSchema(); +export let StateStorage = new StateModel(); diff --git a/packages/bitcore-node/src/models/transaction.ts b/packages/bitcore-node/src/models/transaction.ts index 7093d81773c..a5f126a2e48 100644 --- a/packages/bitcore-node/src/models/transaction.ts +++ b/packages/bitcore-node/src/models/transaction.ts @@ -1,5 +1,5 @@ -import { CoinModel } from './coin'; -import { WalletAddressModel } from './walletAddress'; +import { CoinStorage } from './coin'; +import { WalletAddressStorage } from './walletAddress'; import { partition } from '../utils/partition'; import { ObjectID } from 'bson'; import { TransformOptions } from '../types/TransformOptions'; @@ -35,7 +35,7 @@ export type ITransaction = { }; @LoggifyClass -export class TransactionSchema extends BaseModel { +export class TransactionModel extends BaseModel { constructor(storage?: StorageService) { super('transactions', storage); } @@ -83,7 +83,7 @@ export class TransactionSchema extends BaseModel { if (mintOps.length) { await Promise.all( partition(mintOps, mintOps.length / Config.get().maxPoolSize).map(mintBatch => - CoinModel.collection.bulkWrite(mintBatch, { ordered: false }) + CoinStorage.collection.bulkWrite(mintBatch, { ordered: false }) ) ); } @@ -92,7 +92,7 @@ export class TransactionSchema extends BaseModel { if (spendOps.length) { await Promise.all( partition(spendOps, spendOps.length / Config.get().maxPoolSize).map(spendBatch => - CoinModel.collection.bulkWrite(spendBatch, { ordered: false }) + CoinStorage.collection.bulkWrite(spendBatch, { ordered: false }) ) ); } @@ -140,7 +140,7 @@ export class TransactionSchema extends BaseModel { }) { let { blockHash, blockTime, blockTimeNormalized, chain, height, network, parentChain, forkHeight } = params; if (parentChain && forkHeight && height < forkHeight) { - const parentTxs = await TransactionModel.collection + const parentTxs = await TransactionStorage.collection .find({ blockHeight: height, chain: parentChain, network }) .toArray(); return parentTxs.map(parentTx => { @@ -177,7 +177,7 @@ export class TransactionSchema extends BaseModel { } else { spentQuery = { spentTxid: { $in: params.txs.map(tx => tx._hash) }, chain, network }; } - const spent = await CoinModel.collection + const spent = await CoinStorage.collection .find(spentQuery) .project({ spentTxid: 1, value: 1, wallets: 1 }) .toArray(); @@ -272,7 +272,7 @@ export class TransactionSchema extends BaseModel { let mintOps = new Array(); let parentChainCoinsMap = new Map(); if (parentChain && forkHeight && height < forkHeight) { - let parentChainCoins = await CoinModel.collection + let parentChainCoins = await CoinStorage.collection .find({ chain: parentChain, network, @@ -340,7 +340,7 @@ export class TransactionSchema extends BaseModel { mintOpsAddresses[mintOp.updateOne.update.$set.address] = true; } mintOpsAddresses = Object.keys(mintOpsAddresses); - let wallets = await WalletAddressModel.collection + let wallets = await WalletAddressStorage.collection .find({ address: { $in: mintOpsAddresses }, chain, network }, { batchSize: 100 }) .toArray(); if (wallets.length) { @@ -425,7 +425,7 @@ export class TransactionSchema extends BaseModel { } let prunedTxs = {}; for (const spendOp of spendOps) { - let coin = await CoinModel.collection.findOne( + let coin = await CoinStorage.collection.findOne( { chain, network, @@ -448,7 +448,7 @@ export class TransactionSchema extends BaseModel { { $set: { blockHeight: SpentHeightIndicators.conflicting } }, { w: 0, j: false, multi: true } ), - CoinModel.collection.update( + CoinStorage.collection.update( { mintTxid: { $in: prunedTxs } }, { $set: { mintHeight: SpentHeightIndicators.conflicting } }, { w: 0, j: false, multi: true } @@ -489,4 +489,4 @@ export class TransactionSchema extends BaseModel { return JSON.stringify(transaction); } } -export let TransactionModel = new TransactionSchema(); +export let TransactionStorage = new TransactionModel(); diff --git a/packages/bitcore-node/src/models/wallet.ts b/packages/bitcore-node/src/models/wallet.ts index 7f376e159c8..94f417276eb 100644 --- a/packages/bitcore-node/src/models/wallet.ts +++ b/packages/bitcore-node/src/models/wallet.ts @@ -1,4 +1,4 @@ -import { WalletAddressModel } from '../models/walletAddress'; +import { WalletAddressStorage } from '../models/walletAddress'; import { BaseModel } from './base'; import { TransformOptions } from '../types/TransformOptions'; import { ObjectID } from 'mongodb'; @@ -33,12 +33,12 @@ export class WalletSchema extends BaseModel { } async updateCoins(wallet: IWallet) { - let addressModels = await WalletAddressModel.collection + let addressModels = await WalletAddressStorage.collection .find({ wallet: wallet._id }) .addCursorFlag('noCursorTimeout', true) .toArray(); let addresses = addressModels.map(model => model.address); - return WalletAddressModel.updateCoins({ wallet, addresses }); + return WalletAddressStorage.updateCoins({ wallet, addresses }); } } diff --git a/packages/bitcore-node/src/models/walletAddress.ts b/packages/bitcore-node/src/models/walletAddress.ts index 830f6b53ee8..7513266c418 100644 --- a/packages/bitcore-node/src/models/walletAddress.ts +++ b/packages/bitcore-node/src/models/walletAddress.ts @@ -1,9 +1,9 @@ -import { CoinModel, ICoin } from './coin'; +import { CoinStorage, ICoin } from './coin'; import { TransformOptions } from '../types/TransformOptions'; import { ObjectID } from 'mongodb'; import { BaseModel } from './base'; import { IWallet } from './wallet'; -import { TransactionModel } from './transaction'; +import { TransactionStorage } from './transaction'; import { StorageService } from '../services/storage'; export type IWalletAddress = { @@ -13,7 +13,7 @@ export type IWalletAddress = { network: string; }; -export class WalletAddressSchema extends BaseModel { +export class WalletAddressModel extends BaseModel { constructor(storage?: StorageService) { super('walletaddresses', storage); } @@ -66,14 +66,14 @@ export class WalletAddressSchema extends BaseModel { return new Promise(async resolve => { let batch = new Array(); const AddAddresses = addresses => { - return WalletAddressModel.collection.updateMany( + return WalletAddressStorage.collection.updateMany( { wallet: wallet._id, address: { $in: addresses } }, { $set: { wallet: wallet._id, chain, network } }, { upsert: true } ); }; const UpdateCoins = addresses => { - return CoinModel.collection.updateMany( + return CoinStorage.collection.updateMany( { chain, network, address: { $in: addresses } }, { $addToSet: { wallets: wallet._id } } ); @@ -95,7 +95,7 @@ export class WalletAddressSchema extends BaseModel { batch = new Array(); } - let coinStream = CoinModel.collection + let coinStream = CoinStorage.collection .find({ wallets: wallet._id, 'wallets.0': { $exists: true } }) .project({ spentTxid: 1, mintTxid: 1 }) .addCursorFlag('noCursorTimeout', true); @@ -103,14 +103,14 @@ export class WalletAddressSchema extends BaseModel { coinStream.on('data', (coin: ICoin) => { coinStream.pause(); if (!txids[coin.mintTxid]) { - TransactionModel.collection.updateMany( + TransactionStorage.collection.updateMany( { txid: coin.mintTxid, network, chain }, { $addToSet: { wallets: wallet._id } } ); } txids[coin.mintTxid] = true; if (coin.spentTxid && !txids[coin.spentTxid]) { - TransactionModel.collection.updateMany( + TransactionStorage.collection.updateMany( { txid: coin.spentTxid, network, chain }, { $addToSet: { wallets: wallet._id } } ); @@ -125,4 +125,4 @@ export class WalletAddressSchema extends BaseModel { } } -export let WalletAddressModel = new WalletAddressSchema(); +export let WalletAddressStorage = new WalletAddressModel(); diff --git a/packages/bitcore-node/src/providers/chain-state/eth/eth.ts b/packages/bitcore-node/src/providers/chain-state/eth/eth.ts index 27e5a1e7868..de240e15947 100644 --- a/packages/bitcore-node/src/providers/chain-state/eth/eth.ts +++ b/packages/bitcore-node/src/providers/chain-state/eth/eth.ts @@ -1,5 +1,5 @@ import Config from '../../../config'; -import { WalletAddressModel } from '../../../models/walletAddress'; +import { WalletAddressStorage } from '../../../models/walletAddress'; import { CSP } from '../../../types/namespaces/ChainStateProvider'; import { InternalStateProvider } from '../internal/internal'; import { ObjectID } from 'mongodb'; @@ -54,7 +54,7 @@ export class ETHStateProvider extends InternalStateProvider async getWalletAddresses(walletId: ObjectID) { let query = { wallet: walletId }; - return WalletAddressModel.collection.find(query).addCursorFlag('noCursorTimeout', true).toArray(); + return WalletAddressStorage.collection.find(query).addCursorFlag('noCursorTimeout', true).toArray(); } async getWalletBalance(params: CSP.GetWalletBalanceParams) { diff --git a/packages/bitcore-node/src/providers/chain-state/internal/internal.ts b/packages/bitcore-node/src/providers/chain-state/internal/internal.ts index 37a76791adf..08e460698b1 100644 --- a/packages/bitcore-node/src/providers/chain-state/internal/internal.ts +++ b/packages/bitcore-node/src/providers/chain-state/internal/internal.ts @@ -3,18 +3,18 @@ import through2 from 'through2'; import { MongoBound } from '../../../models/base'; import { ObjectId } from 'mongodb'; -import { CoinModel, ICoin } from '../../../models/coin'; -import { BlockModel, IBlock } from '../../../models/block'; +import { CoinStorage, ICoin } from '../../../models/coin'; +import { BlockStorage, IBlock } from '../../../models/block'; import { WalletModel, IWallet } from '../../../models/wallet'; -import { WalletAddressModel } from '../../../models/walletAddress'; +import { WalletAddressStorage } from '../../../models/walletAddress'; import { CSP } from '../../../types/namespaces/ChainStateProvider'; import { Storage } from '../../../services/storage'; import { RPC } from '../../../rpc'; import { LoggifyClass } from '../../../decorators/Loggify'; -import { TransactionModel, ITransaction } from '../../../models/transaction'; +import { TransactionStorage, ITransaction } from '../../../models/transaction'; import { ListTransactionsStream } from './transforms'; import { StringifyJsonStream } from '../../../utils/stringifyJsonStream'; -import { StateModel } from '../../../models/state'; +import { StateStorage } from '../../../models/state'; import { SpentHeightIndicators, CoinJSON } from '../../../types/Coin'; import { Config } from '../../../services/config'; @@ -51,38 +51,38 @@ export class InternalStateProvider implements CSP.IChainStateService { const { req, res, args } = params; const { limit } = args; const query = this.getAddressQuery(params); - Storage.apiStreamingFind(CoinModel, query, { limit }, req, res); + Storage.apiStreamingFind(CoinStorage, query, { limit }, req, res); } async streamAddressTransactions(params: CSP.StreamAddressUtxosParams) { const { args, req, res } = params; const { limit = 10 } = args; const query = this.getAddressQuery(params); - Storage.apiStreamingFind(CoinModel, query, { limit }, req, res); + Storage.apiStreamingFind(CoinStorage, query, { limit }, req, res); } async getBalanceForAddress(params: CSP.GetBalanceForAddressParams) { const { chain, network, address } = params; let query = { chain, network, address }; - let balance = await CoinModel.getBalance({ query }); + let balance = await CoinStorage.getBalance({ query }); return balance; } async getBalanceForWallet(params: CSP.GetBalanceForWalletParams) { const { walletId } = params; let query = { wallets: walletId }; - return CoinModel.getBalance({ query }); + return CoinStorage.getBalance({ query }); } streamBlocks(params: CSP.StreamBlocksParams) { const { req, res } = params; const { query, options } = this.getBlocksQuery(params); - Storage.apiStreamingFind(BlockModel, query, options, req, res); + Storage.apiStreamingFind(BlockStorage, query, options, req, res); } async getBlocks(params: CSP.GetBlockParams) { const { query, options } = this.getBlocksQuery(params); - let cursor = BlockModel.collection.find(query, options).addCursorFlag('noCursorTimeout', true); + let cursor = BlockStorage.collection.find(query, options).addCursorFlag('noCursorTimeout', true); if (options.sort) { cursor = cursor.sort(options.sort); } @@ -94,7 +94,7 @@ export class InternalStateProvider implements CSP.IChainStateService { if (b.height && b.height >= 0) { confirmations = tipHeight - b.height + 1; } - const convertedBlock = BlockModel._apiTransform(b, { object: true }) as IBlock; + const convertedBlock = BlockStorage._apiTransform(b, { object: true }) as IBlock; return { ...convertedBlock, confirmations }; }; return blocks.map(blockTransform); @@ -169,12 +169,12 @@ export class InternalStateProvider implements CSP.IChainStateService { } const tip = await this.getLocalTip(params); const tipHeight = tip ? tip.height : 0; - return Storage.apiStreamingFind(TransactionModel, query, args, req, res, t => { + return Storage.apiStreamingFind(TransactionStorage, query, args, req, res, t => { let confirmations = 0; if (t.blockHeight !== undefined && t.blockHeight >= 0) { confirmations = tipHeight - t.blockHeight + 1; } - const convertedTx = TransactionModel._apiTransform(t, { object: true }) as Partial; + const convertedTx = TransactionStorage._apiTransform(t, { object: true }) as Partial; return JSON.stringify({ ...convertedTx, confirmations: confirmations }); }); } @@ -188,13 +188,13 @@ export class InternalStateProvider implements CSP.IChainStateService { let query = { chain: chain, network, txid: txId }; const tip = await this.getLocalTip(params); const tipHeight = tip ? tip.height : 0; - const found = await TransactionModel.collection.findOne(query); + const found = await TransactionStorage.collection.findOne(query); if (found) { let confirmations = 0; if (found.blockHeight && found.blockHeight >= 0) { confirmations = tipHeight - found.blockHeight + 1; } - const convertedTx = TransactionModel._apiTransform(found, { object: true }) as TransactionJSON; + const convertedTx = TransactionStorage._apiTransform(found, { object: true }) as TransactionJSON; return { ...convertedTx, confirmations: confirmations }; } else { return undefined; @@ -206,10 +206,10 @@ export class InternalStateProvider implements CSP.IChainStateService { if (typeof txId !== 'string') { throw 'Missing required param'; } - const found = (await CoinModel.resolveAuthhead(txId, chain, network))[0]; + const found = (await CoinStorage.resolveAuthhead(txId, chain, network))[0]; if (found) { const transformedCoins = found.identityOutputs.map(output => - CoinModel._apiTransform(output, { object: true }) + CoinStorage._apiTransform(output, { object: true }) ); return { chain: found.chain, @@ -227,7 +227,7 @@ export class InternalStateProvider implements CSP.IChainStateService { if (typeof name !== 'string' || !network) { throw 'Missing required param'; } - const state = await StateModel.collection.findOne({}); + const state = await StateStorage.collection.findOne({}); const initialSyncComplete = state && state.initialSyncComplete && state.initialSyncComplete.includes(`${chain}:${network}`); if (!initialSyncComplete && !Config.for('api').wallets.allowCreationBeforeCompleteSync) { @@ -253,7 +253,7 @@ export class InternalStateProvider implements CSP.IChainStateService { streamWalletAddresses(params: CSP.StreamWalletAddressesParams) { let { walletId, limit = 1000, req, res } = params; let query = { wallet: walletId }; - Storage.apiStreamingFind(WalletAddressModel, query, { limit }, req, res); + Storage.apiStreamingFind(WalletAddressStorage, query, { limit }, req, res); } async streamMissingWalletAddresses(params: CSP.StreamWalletMissingAddressesParams) { @@ -261,7 +261,7 @@ export class InternalStateProvider implements CSP.IChainStateService { const wallet = await WalletModel.collection.findOne({ pubKey }); const walletId = wallet!._id!; const query = { chain, network, wallets: walletId, spentHeight: { $gte: SpentHeightIndicators.minimum } }; - const cursor = CoinModel.collection.find(query).addCursorFlag('noCursorTimeout', true); + const cursor = CoinStorage.collection.find(query).addCursorFlag('noCursorTimeout', true); const seen = {}; const stringifyWallets = (wallets: Array) => wallets.map(w => w.toHexString()); const allMissingAddresses = new Array(); @@ -273,7 +273,7 @@ export class InternalStateProvider implements CSP.IChainStateService { if (!seen[spentCoin.spentTxid]) { seen[spentCoin.spentTxid] = true; // find coins that were spent with my coins - const spends = await CoinModel.collection + const spends = await CoinStorage.collection .find({ chain, network, spentTxid: spentCoin.spentTxid }) .addCursorFlag('noCursorTimeout', true) .toArray(); @@ -302,7 +302,7 @@ export class InternalStateProvider implements CSP.IChainStateService { async updateWallet(params: CSP.UpdateWalletParams) { const { wallet, addresses } = params; - return WalletAddressModel.updateCoins({ wallet, addresses }); + return WalletAddressStorage.updateCoins({ wallet, addresses }); } async streamWalletTransactions(params: CSP.StreamWalletTransactionsParams) { @@ -345,7 +345,7 @@ export class InternalStateProvider implements CSP.IChainStateService { } } - const transactionStream = TransactionModel.collection + const transactionStream = TransactionStorage.collection .find(query) .sort({ blockTimeNormalized: 1 }) .addCursorFlag('noCursorTimeout', true); @@ -355,7 +355,7 @@ export class InternalStateProvider implements CSP.IChainStateService { async getWalletBalance(params: CSP.GetWalletBalanceParams) { let query = { wallets: params.wallet._id, 'wallets.0': { $exists: true } }; - return CoinModel.getBalance({ query }); + return CoinStorage.getBalance({ query }); } async streamWalletUtxos(params: CSP.StreamWalletUtxosParams) { @@ -376,10 +376,10 @@ export class InternalStateProvider implements CSP.IChainStateService { confirmations = tipHeight - c.mintHeight + 1; } c.confirmations = confirmations; - return CoinModel._apiTransform(c) as string; + return CoinStorage._apiTransform(c) as string; }; - Storage.apiStreamingFind(CoinModel, query, { limit }, req, res, utxoTransform); + Storage.apiStreamingFind(CoinStorage, query, { limit }, req, res, utxoTransform); } async getFee(params: CSP.GetEstimateSmartFeeParams) { @@ -401,12 +401,12 @@ export class InternalStateProvider implements CSP.IChainStateService { } async getCoinsForTx({ chain, network, txid }: { chain: string; network: string; txid: string }) { - const tx = await TransactionModel.collection.find({ txid }).count(); + const tx = await TransactionStorage.collection.find({ txid }).count(); if (tx === 0) { throw new Error(`No such transaction ${txid}`); } - let inputs = await CoinModel.collection + let inputs = await CoinStorage.collection .find({ chain, network, @@ -415,7 +415,7 @@ export class InternalStateProvider implements CSP.IChainStateService { .addCursorFlag('noCursorTimeout', true) .toArray(); - const outputs = await CoinModel.collection + const outputs = await CoinStorage.collection .find({ chain, network, @@ -425,15 +425,15 @@ export class InternalStateProvider implements CSP.IChainStateService { .toArray(); return { - inputs: inputs.map(input => CoinModel._apiTransform(input, { object: true })), - outputs: outputs.map(output => CoinModel._apiTransform(output, { object: true })) + inputs: inputs.map(input => CoinStorage._apiTransform(input, { object: true })), + outputs: outputs.map(output => CoinStorage._apiTransform(output, { object: true })) }; } async getDailyTransactions({ chain, network }: { chain: string; network: string }) { const beforeBitcoin = new Date('2009-01-09T00:00:00.000Z'); const todayTruncatedUTC = new Date(new Date().toISOString().split('T')[0]); - const results = await BlockModel.collection + const results = await BlockStorage.collection .aggregate<{ date: string; transactionCount: number; @@ -483,16 +483,16 @@ export class InternalStateProvider implements CSP.IChainStateService { } async getLocalTip({ chain, network }) { - if (BlockModel.chainTips[chain] && BlockModel.chainTips[chain][network]) { - return BlockModel.chainTips[chain][network]; + if (BlockStorage.chainTips[chain] && BlockStorage.chainTips[chain][network]) { + return BlockStorage.chainTips[chain][network]; } else { - return BlockModel.getLocalTip({ chain, network }); + return BlockStorage.getLocalTip({ chain, network }); } } async getLocatorHashes(params) { const { chain, network } = params; - const locatorBlocks = await BlockModel.collection + const locatorBlocks = await BlockStorage.collection .find( { processed: true, diff --git a/packages/bitcore-node/src/providers/chain-state/internal/transforms.ts b/packages/bitcore-node/src/providers/chain-state/internal/transforms.ts index 8d5ee81d990..f5bdd00a245 100644 --- a/packages/bitcore-node/src/providers/chain-state/internal/transforms.ts +++ b/packages/bitcore-node/src/providers/chain-state/internal/transforms.ts @@ -1,4 +1,4 @@ -import { CoinModel } from '../../../models/coin'; +import { CoinStorage } from '../../../models/coin'; import { Transform } from 'stream'; import { IWallet } from '../../../models/wallet'; @@ -8,7 +8,7 @@ export class ListTransactionsStream extends Transform { } async _transform(transaction, _, done) { - const sending = !! await CoinModel.collection.count({ + const sending = !! await CoinStorage.collection.count({ wallets: this.wallet._id, 'wallets.0': { $exists: true }, spentTxid: transaction.txid @@ -17,7 +17,7 @@ export class ListTransactionsStream extends Transform { const wallet = this.wallet._id!.toString(); if (sending) { - const outputs = await CoinModel.collection + const outputs = await CoinStorage.collection .find( { chain: transaction.chain, @@ -79,7 +79,7 @@ export class ListTransactionsStream extends Transform { } return done(); } else { - const outputs = await CoinModel.collection.find({ + const outputs = await CoinStorage.collection.find({ wallets: this.wallet._id, 'wallets.0': { $exists: true }, mintTxid: transaction.txid diff --git a/packages/bitcore-node/src/routes/middleware.ts b/packages/bitcore-node/src/routes/middleware.ts index 200aabbf6fe..2806efdaa2a 100644 --- a/packages/bitcore-node/src/routes/middleware.ts +++ b/packages/bitcore-node/src/routes/middleware.ts @@ -1,6 +1,6 @@ import logger from '../logger'; import * as express from 'express'; -import { RateLimitModel } from '../models/rateLimit'; +import { RateLimitStorage } from '../models/rateLimit'; import { Config } from "../services/config"; type TimedRequest = { @@ -74,7 +74,7 @@ export function RateLimiter(method: string, perSecond: number, perMinute: number if (Config.for('api').rateLimiter.whitelist.includes(identifier)) { return next(); } - let [perSecondResult, perMinuteResult, perHourResult] = await RateLimitModel.incrementAndCheck( + let [perSecondResult, perMinuteResult, perHourResult] = await RateLimitStorage.incrementAndCheck( identifier, method ); diff --git a/packages/bitcore-node/src/server.ts b/packages/bitcore-node/src/server.ts index 5dab5d970e4..9b383015a0a 100755 --- a/packages/bitcore-node/src/server.ts +++ b/packages/bitcore-node/src/server.ts @@ -11,16 +11,14 @@ process.on('unhandledRejection', error => { console.error('Unhandled Rejection at:', error.stack || error); }); -const startServices = async () => { - await Worker.start(); - await P2P.start(); -}; const runMaster = async () => { - await startServices(); + await Worker.start(); + P2P.start(); + // start the API on master if we are in debug if (args.DEBUG) { - await Api.start(); + Api.start(); } }; @@ -28,13 +26,13 @@ const runWorker = async () => { // don't run any workers when in debug mode if (!args.DEBUG) { // Api will automatically start storage if it isn't already running - await Api.start(); + Api.start(); } }; const start = async () => { await Storage.start({}); - await Event.start(); + Event.start(); if (cluster.isMaster) { await runMaster(); } else { diff --git a/packages/bitcore-node/src/services/event.ts b/packages/bitcore-node/src/services/event.ts index 79dd078c534..8322ace5dd3 100644 --- a/packages/bitcore-node/src/services/event.ts +++ b/packages/bitcore-node/src/services/event.ts @@ -1,7 +1,7 @@ import logger from '../logger'; import { StorageService } from './storage'; import { LoggifyClass } from '../decorators/Loggify'; -import { EventModel, IEvent, EventSchema } from '../models/events'; +import { EventStorage, IEvent, EventModel } from '../models/events'; import { PassThrough } from 'stream'; import { Storage } from './storage'; import { Config, ConfigService } from './config'; @@ -13,10 +13,10 @@ export class EventService { addressCoinStream = new PassThrough({ objectMode: true }); storageService: StorageService; configService: ConfigService; - eventModel: EventSchema; + eventModel: EventModel; stopped = false; - constructor({ storageService = Storage, eventModel = EventModel, configService = Config } = {}) { + constructor({ storageService = Storage, eventModel = EventStorage, configService = Config } = {}) { this.storageService = storageService; this.configService = configService; this.eventModel = eventModel; diff --git a/packages/bitcore-node/src/services/p2p.ts b/packages/bitcore-node/src/services/p2p.ts index ccaabe967d4..1614ebb3ee8 100644 --- a/packages/bitcore-node/src/services/p2p.ts +++ b/packages/bitcore-node/src/services/p2p.ts @@ -1,10 +1,10 @@ import logger from '../logger'; import { EventEmitter } from 'events'; -import { BlockModel, BlockSchema } from '../models/block'; +import { BlockStorage, BlockModel } from '../models/block'; import { ChainStateProvider } from '../providers/chain-state'; -import { TransactionModel } from '../models/transaction'; +import { TransactionStorage } from '../models/transaction'; import { Bitcoin } from '../types/namespaces/Bitcoin'; -import { StateModel } from '../models/state'; +import { StateStorage } from '../models/state'; import { SpentHeightIndicators } from '../types/Coin'; import { Config, ConfigService } from './config'; import { ConfigType } from '../types/Config'; @@ -27,7 +27,7 @@ export class P2pManager { } } - async start({ blockModel = BlockModel } = {}) { + async start({ blockModel = BlockStorage } = {}) { if (!this.configService.isEnabled('p2p')) { return; } @@ -68,8 +68,8 @@ export class P2pWorker { private connectInterval?: NodeJS.Timer; private invCache: any; private initialSyncComplete: boolean; - private blockModel: BlockSchema; - constructor({ chain, network, chainConfig, blockModel = BlockModel }) { + private blockModel: BlockModel; + constructor({ chain, network, chainConfig, blockModel = BlockStorage }) { this.blockModel = blockModel; this.chain = chain; this.network = network; @@ -263,7 +263,7 @@ export class P2pWorker { async processTransaction(tx: Bitcoin.Transaction): Promise { const now = new Date(); - TransactionModel.batchImport({ + TransactionStorage.batchImport({ chain: this.chain, network: this.network, txs: [tx], @@ -282,7 +282,7 @@ export class P2pWorker { this.syncing = true; const { chain, chainConfig, network } = this; const { parentChain, forkHeight } = chainConfig; - const state = await StateModel.collection.findOne({}); + const state = await StateStorage.collection.findOne({}); this.initialSyncComplete = state && state.initialSyncComplete && state.initialSyncComplete.includes(`${chain}:${network}`); let tip = await ChainStateProvider.getLocalTip({ chain, network }); @@ -331,7 +331,7 @@ export class P2pWorker { } logger.info(`${chain}:${network} up to date.`); this.syncing = false; - StateModel.collection.findOneAndUpdate( + StateStorage.collection.findOneAndUpdate( {}, { $addToSet: { initialSyncComplete: `${chain}:${network}` } }, { upsert: true } diff --git a/packages/bitcore-node/src/services/socket.ts b/packages/bitcore-node/src/services/socket.ts index a6e95a91c77..14ac0e51d49 100644 --- a/packages/bitcore-node/src/services/socket.ts +++ b/packages/bitcore-node/src/services/socket.ts @@ -2,7 +2,7 @@ import logger from '../logger'; import SocketIO = require('socket.io'); import * as http from 'http'; import { LoggifyClass } from '../decorators/Loggify'; -import { EventModel, IEvent, EventSchema } from '../models/events'; +import { EventStorage, EventModel, IEvent } from '../models/events'; import { Event, EventService } from './event'; import { ObjectID } from 'mongodb'; import { Config, ConfigService } from './config'; @@ -24,9 +24,9 @@ export class SocketService { configService: ConfigService; serviceConfig: ConfigType['services']['socket']; eventService: EventService; - eventModel: EventSchema; + eventModel: EventModel; - constructor({ eventService = Event, eventModel = EventModel, configService = Config } = {}) { + constructor({ eventService = Event, eventModel = EventStorage, configService = Config } = {}) { this.eventService = eventService; this.configService = configService; this.serviceConfig = this.configService.for('socket'); @@ -91,15 +91,15 @@ export class SocketService { } async signalBlock(block: IEvent.BlockEvent) { - await EventModel.signalBlock(block); + await EventStorage.signalBlock(block); } async signalTx(tx: IEvent.TxEvent) { - await EventModel.signalTx(tx); + await EventStorage.signalTx(tx); } async signalAddressCoin(payload: IEvent.CoinEvent) { - await EventModel.signalAddressCoin(payload); + await EventStorage.signalAddressCoin(payload); } } diff --git a/packages/bitcore-node/test/benchmark/benchmark.ts b/packages/bitcore-node/test/benchmark/benchmark.ts index d074435bfbb..ead8779e7d4 100644 --- a/packages/bitcore-node/test/benchmark/benchmark.ts +++ b/packages/bitcore-node/test/benchmark/benchmark.ts @@ -4,7 +4,7 @@ const UnspentOutput = Transaction.UnspentOutput; import config from '../../src/config'; import { Storage } from '../../src/services/storage'; -import { BlockModel } from '../../src/models/block'; +import { BlockStorage } from '../../src/models/block'; import { BitcoinBlockType } from '../../src/types/namespaces/Bitcoin/Block'; import { resetDatabase } from '../helpers/index.js'; import * as crypto from 'crypto'; @@ -123,7 +123,7 @@ async function benchmark(blockCount: number, blockSizeMb: number) { console.log('Adding blocks'); for (let block of blocks) { process.stdout.write('.'); - await BlockModel.addBlock({ block, chain: 'BENCH', network: 'MARK', initialSyncComplete: false }); + await BlockStorage.addBlock({ block, chain: 'BENCH', network: 'MARK', initialSyncComplete: false }); } process.stdout.write('\n'); const endTime = new Date(); diff --git a/packages/bitcore-node/test/benchmark/wallet-benchmark.ts b/packages/bitcore-node/test/benchmark/wallet-benchmark.ts index 4522e39222a..0b644b7e65c 100644 --- a/packages/bitcore-node/test/benchmark/wallet-benchmark.ts +++ b/packages/bitcore-node/test/benchmark/wallet-benchmark.ts @@ -1,10 +1,10 @@ -import { CoinModel } from '../../src/models/coin'; +import { CoinStorage } from '../../src/models/coin'; import { Wallet } from 'bitcore-client'; import { Storage } from '../../src/services/storage'; async function getAllAddressesFromBlocks(start, end) { if (!Storage.connected) await Storage.start({}); - const addresses = await CoinModel.collection + const addresses = await CoinStorage.collection .find({ chain: 'BTC', network: 'mainnet', mintHeight: { $gte: start, $lte: end } }) .project({ address: 1 }) .toArray(); diff --git a/packages/bitcore-node/test/helpers/index.ts b/packages/bitcore-node/test/helpers/index.ts index 277f1d5bd64..05cae6e7f9c 100644 --- a/packages/bitcore-node/test/helpers/index.ts +++ b/packages/bitcore-node/test/helpers/index.ts @@ -1,17 +1,17 @@ import * as sinon from 'sinon'; -import { BlockModel } from '../../src/models/block'; -import { TransactionModel } from '../../src/models/transaction'; -import { CoinModel } from '../../src/models/coin'; -import { WalletAddressModel } from '../../src/models/walletAddress'; +import { BlockStorage } from '../../src/models/block'; +import { TransactionStorage } from '../../src/models/transaction'; +import { CoinStorage } from '../../src/models/coin'; +import { WalletAddressStorage } from '../../src/models/walletAddress'; import { WalletModel } from '../../src/models/wallet'; import { Storage } from '../../src/services/storage'; import { BaseModel } from '../../src/models/base'; export async function resetDatabase() { - await resetModel(BlockModel); - await resetModel(TransactionModel); - await resetModel(CoinModel); - await resetModel(WalletAddressModel); + await resetModel(BlockStorage); + await resetModel(TransactionStorage); + await resetModel(CoinStorage); + await resetModel(WalletAddressStorage); await resetModel(WalletModel); } diff --git a/packages/bitcore-node/test/integration/models/block.integration.ts b/packages/bitcore-node/test/integration/models/block.integration.ts index 7d92e037a56..4ebba281ee2 100644 --- a/packages/bitcore-node/test/integration/models/block.integration.ts +++ b/packages/bitcore-node/test/integration/models/block.integration.ts @@ -1,8 +1,8 @@ import { expect } from 'chai'; import { resetDatabase } from '../../helpers'; -import { BlockModel } from '../../../src/models/block'; -import { TransactionModel } from '../../../src/models/transaction'; -import { CoinModel } from '../../../src/models/coin'; +import { BlockStorage } from '../../../src/models/block'; +import { TransactionStorage } from '../../../src/models/transaction'; +import { CoinStorage } from '../../../src/models/coin'; import { TEST_BLOCK } from '../../data/test-block'; import { SpentHeightIndicators } from '../../../src/types/Coin'; import logger from '../../../src/logger'; @@ -14,7 +14,7 @@ describe('Block Model', function() { describe('addBlock', () => { it('should add a block when incoming block references previous block hash', async () => { - await BlockModel.collection.insertOne({ + await BlockStorage.collection.insertOne({ chain: 'BTC', network: 'regtest', height: 5, @@ -32,7 +32,7 @@ describe('Block Model', function() { bits: parseInt('207fffff', 16), processed: true }); - await BlockModel.collection.insertOne({ + await BlockStorage.collection.insertOne({ chain: 'BTC', network: 'regtest', height: 6, @@ -50,7 +50,7 @@ describe('Block Model', function() { bits: parseInt('207fffff', 16), processed: true }); - await BlockModel.collection.insertOne({ + await BlockStorage.collection.insertOne({ chain: 'BTC', network: 'regtest', height: 7, @@ -68,7 +68,7 @@ describe('Block Model', function() { bits: parseInt('207fffff', 16), processed: true }); - await BlockModel.collection.insertOne({ + await BlockStorage.collection.insertOne({ chain: 'BTC', network: 'regtest', height: 8, @@ -87,9 +87,9 @@ describe('Block Model', function() { processed: true }); - await BlockModel.addBlock({ block: TEST_BLOCK, chain: 'BTC', network: 'regtest', initialSyncComplete: false }); + await BlockStorage.addBlock({ block: TEST_BLOCK, chain: 'BTC', network: 'regtest', initialSyncComplete: false }); - const blocks = await BlockModel.collection + const blocks = await BlockStorage.collection .find({ chain: 'BTC', network: 'regtest' }) .sort({ height: 1 }) .toArray(); @@ -112,7 +112,7 @@ describe('Block Model', function() { logger.info(`new block was successfully added with hash`, ownBlock.hash); - const transaction = await TransactionModel.collection + const transaction = await TransactionStorage.collection .find({ chain: 'BTC', network: 'regtest', @@ -137,7 +137,7 @@ describe('Block Model', function() { describe('handleReorg', () => { it("should not reorg if the incoming block's prevHash matches the block hash of the current highest block", async () => { - await BlockModel.collection.insertOne({ + await BlockStorage.collection.insertOne({ chain: 'BTC', network: 'regtest', height: 1335, @@ -155,7 +155,7 @@ describe('Block Model', function() { bits: parseInt('207fffff', 16), processed: true }); - await BlockModel.collection.insertOne({ + await BlockStorage.collection.insertOne({ chain: 'BTC', network: 'regtest', height: 1336, @@ -173,7 +173,7 @@ describe('Block Model', function() { bits: parseInt('207fffff', 16), processed: true }); - await BlockModel.collection.insertOne({ + await BlockStorage.collection.insertOne({ chain: 'BTC', network: 'regtest', height: 1337, @@ -192,7 +192,7 @@ describe('Block Model', function() { processed: true }); - await BlockModel.handleReorg({ + await BlockStorage.handleReorg({ header: { prevHash: '3279069d22ce5af68ef38332d5b40e79e1964b154d466e7fa233015a34c27312', hash: '12c719927ce18f9a61d7c5a7af08d3110cacfa43671aa700956c3c05ed38bdaa', @@ -206,11 +206,11 @@ describe('Block Model', function() { network: 'regtest' }); - const result = await BlockModel.collection.find({ chain: 'BTC', network: 'regtest' }).toArray(); + const result = await BlockStorage.collection.find({ chain: 'BTC', network: 'regtest' }).toArray(); expect(result.length).to.equal(3); }); it('should not reorg if localTip height is zero', async () => { - await BlockModel.handleReorg({ + await BlockStorage.handleReorg({ header: { prevHash: '12c719927ce18f9a61d7c5a7af08d3110cacfa43671aa700956c3c05ed38bdaa', hash: '4c6872bf45ecab2fb8b38c8b8f50fc4a8309c6171d28d479b8226afcb1a99920', @@ -224,12 +224,12 @@ describe('Block Model', function() { network: 'regtest' }); - const result = await BlockModel.collection.find({ chain: 'BTC', network: 'regtest' }).toArray(); + const result = await BlockStorage.collection.find({ chain: 'BTC', network: 'regtest' }).toArray(); expect(result.length).to.equal(0); }); it('should successfully handle reorg', async () => { // setting the Block model - await BlockModel.collection.insertOne({ + await BlockStorage.collection.insertOne({ chain: 'BTC', network: 'regtest', height: 5, @@ -247,7 +247,7 @@ describe('Block Model', function() { bits: parseInt('207fffff', 16), processed: true }); - await BlockModel.collection.insertOne({ + await BlockStorage.collection.insertOne({ chain: 'BTC', network: 'regtest', height: 6, @@ -265,7 +265,7 @@ describe('Block Model', function() { bits: parseInt('207fffff', 16), processed: true }); - await BlockModel.collection.insertOne({ + await BlockStorage.collection.insertOne({ chain: 'BTC', network: 'regtest', height: 7, @@ -285,7 +285,7 @@ describe('Block Model', function() { }); // setting TX model - await TransactionModel.collection.insertOne({ + await TransactionStorage.collection.insertOne({ txid: 'a2262b524615b6d2f409784ceff898fd46bdde6a584269788c41f26ac4b4919g', chain: 'BTC', network: 'regtest', @@ -302,7 +302,7 @@ describe('Block Model', function() { blockHeight: 5 }); - await TransactionModel.collection.insertOne({ + await TransactionStorage.collection.insertOne({ txid: '8c29860888b915715878b21ce14707a17b43f6c51dfb62a1e736e35bc5d8093f', chain: 'BTC', network: 'regtest', @@ -319,7 +319,7 @@ describe('Block Model', function() { blockHeight: 6 }); - await TransactionModel.collection.insertOne({ + await TransactionStorage.collection.insertOne({ txid: 'a2262b524615b6d2f409784ceff898fd46bdde6a584269788c41f26ac4b4919e', chain: 'BTC', network: 'regtest', @@ -336,7 +336,7 @@ describe('Block Model', function() { blockHeight: 7 }); - await TransactionModel.collection.insertOne({ + await TransactionStorage.collection.insertOne({ txid: '8a351fa9fc3fcd38066b4bf61a8b5f71f08aa224d7a86165557e6da7ee13a826', chain: 'BTC', network: 'regtest', @@ -354,7 +354,7 @@ describe('Block Model', function() { }); // setting the Coin model - await CoinModel.collection.insertOne({ + await CoinStorage.collection.insertOne({ network: 'regtest', chain: 'BTC', mintTxid: 'a2262b524615b6d2f409784ceff898fd46bdde6a584269788c41f26ac4b4919g', @@ -369,7 +369,7 @@ describe('Block Model', function() { address: 'mkjB6LmjiNfJWgH4aP4v1GkFjRcQTfDSfj' }); - await CoinModel.collection.insertOne({ + await CoinStorage.collection.insertOne({ network: 'regtest', chain: 'BTC', mintTxid: 'a2262b524615b6d2f409784ceff898fd46bdde6a584269788c41f26ac4b4919e', @@ -383,7 +383,7 @@ describe('Block Model', function() { value: 500.0, address: 'mkjB6LmjiNfJWgH4aP4v1GkFjRcQTfDSfj' }); - await CoinModel.collection.insertOne({ + await CoinStorage.collection.insertOne({ network: 'regtest', chain: 'BTC', mintTxid: '8a351fa9fc3fcd38066b4bf61a8b5f71f08aa224d7a86165557e6da7ee13a826', @@ -397,7 +397,7 @@ describe('Block Model', function() { value: 500.0, address: 'mkjB6LmjiNfJWgH4aP4v1GkFjRcQTfDSfj' }); - await CoinModel.collection.insertOne({ + await CoinStorage.collection.insertOne({ network: 'regtest', chain: 'BTC', mintTxid: '8c29860888b915715878b21ce14707a17b43f6c51dfb62a1e736e35bc5d8093f', @@ -412,7 +412,7 @@ describe('Block Model', function() { spentTxid: 'eec8570a0c960b19fa6c86c71a06ebda379b86b5fe0be0e64ba83b2e0a3d05a3' }); - await BlockModel.handleReorg({ + await BlockStorage.handleReorg({ header: { prevHash: '2a883ff89c7d6e9302bb4a4634cd580319a4fd59d69e979b344972b0ba042b86', hash: '3279069d22ce5af68ef38332d5b40e79e1964b154d466e7fa233015a34c27312', @@ -427,7 +427,7 @@ describe('Block Model', function() { }); // check for removed block after Reorg in db - const blocks = await BlockModel.collection + const blocks = await BlockStorage.collection .find({ chain: 'BTC', network: 'regtest' @@ -435,7 +435,7 @@ describe('Block Model', function() { .toArray(); expect(blocks.length).to.equal(1); - const removedBlock = await BlockModel.collection + const removedBlock = await BlockStorage.collection .find({ chain: 'BTC', network: 'regtest', @@ -447,7 +447,7 @@ describe('Block Model', function() { expect(removedBlock.length).to.equal(0); // check for removed tx after Reorg in db - const transaction = await TransactionModel.collection + const transaction = await TransactionStorage.collection .find({ chain: 'BTC', network: 'regtest' @@ -455,7 +455,7 @@ describe('Block Model', function() { .toArray(); expect(transaction.length).to.equal(1); - const removedTransaction = await TransactionModel.collection + const removedTransaction = await TransactionStorage.collection .find({ chain: 'BTC', network: 'regtest', @@ -467,7 +467,7 @@ describe('Block Model', function() { expect(removedTransaction.length).to.equal(0); // check for removed coin after Reorg in db - const coinModel = await CoinModel.collection + const coinModel = await CoinStorage.collection .find({ chain: 'BTC', network: 'regtest' @@ -475,7 +475,7 @@ describe('Block Model', function() { .toArray(); expect(coinModel.length).to.equal(1); - const removedCoin = await CoinModel.collection + const removedCoin = await CoinStorage.collection .find({ chain: 'BTC', network: 'regtest', @@ -487,7 +487,7 @@ describe('Block Model', function() { expect(removedCoin.length).to.equal(0); // check for unspent coins in the db - const unspentCoins = await CoinModel.collection + const unspentCoins = await CoinStorage.collection .find({ chain: 'BTC', network: 'regtest', diff --git a/packages/bitcore-node/test/unit/models/block.unit.ts b/packages/bitcore-node/test/unit/models/block.unit.ts index 3b99969da4e..e6043510ca3 100644 --- a/packages/bitcore-node/test/unit/models/block.unit.ts +++ b/packages/bitcore-node/test/unit/models/block.unit.ts @@ -1,7 +1,7 @@ import { expect } from 'chai'; -import { BlockModel, IBlock } from '../../../src/models/block'; -import { TransactionModel } from '../../../src/models/transaction'; -import { CoinModel } from '../../../src/models/coin'; +import { BlockStorage, IBlock } from '../../../src/models/block'; +import { TransactionStorage } from '../../../src/models/transaction'; +import { CoinStorage } from '../../../src/models/coin'; import * as sinon from 'sinon'; import { TEST_BLOCK } from '../../data/test-block'; import { Storage } from '../../../src/services/storage'; @@ -28,13 +28,13 @@ describe('Block Model', function() { sandbox.restore(); }); it('should be able to add a block', async () => { - let newBlock = Object.assign({ save: () => Promise.resolve() }, BlockModel, addBlockParams); + let newBlock = Object.assign({ save: () => Promise.resolve() }, BlockStorage, addBlockParams); mockStorage(newBlock); - sandbox.stub(BlockModel, 'handleReorg').resolves(); - sandbox.stub(TransactionModel, 'batchImport').resolves(); + sandbox.stub(BlockStorage, 'handleReorg').resolves(); + sandbox.stub(TransactionStorage, 'batchImport').resolves(); - const result = await BlockModel.addBlock(addBlockParams); + const result = await BlockStorage.addBlock(addBlockParams); expect(result); }); }); @@ -42,7 +42,7 @@ describe('Block Model', function() { describe('BlockModel find options', () => { it('should be able to create query options', () => { const id = new ObjectID(); - const { query, options } = Storage.getFindOptions>(BlockModel, { + const { query, options } = Storage.getFindOptions>(BlockStorage, { since: id, paging: '_id', limit: 100, @@ -55,7 +55,7 @@ describe('Block Model', function() { it('should default to descending', () => { const id = new ObjectID(); - const { query, options } = Storage.getFindOptions>(BlockModel, { + const { query, options } = Storage.getFindOptions>(BlockStorage, { since: id, paging: '_id', limit: 100, @@ -67,7 +67,7 @@ describe('Block Model', function() { it('should allow ascending', () => { const id = new ObjectID(); - const { query, options } = Storage.getFindOptions>(BlockModel, { + const { query, options } = Storage.getFindOptions>(BlockStorage, { since: id, paging: '_id', limit: 100, @@ -124,13 +124,13 @@ describe('Block Model', function() { }); it('should return if localTip hash equals the previous hash', async () => { - Object.assign(BlockModel.collection, mockCollection(null)); - Object.assign(TransactionModel.collection, mockCollection(null)); - Object.assign(CoinModel.collection, mockCollection(null)); - let blockModelRemoveSpy = BlockModel.collection.deleteMany as sinon.SinonSpy; - let transactionModelRemoveSpy = TransactionModel.collection.deleteMany as sinon.SinonSpy; - let coinModelRemoveSpy = CoinModel.collection.deleteMany as sinon.SinonSpy; - let coinModelUpdateSpy = CoinModel.collection.updateMany as sinon.SinonSpy; + Object.assign(BlockStorage.collection, mockCollection(null)); + Object.assign(TransactionStorage.collection, mockCollection(null)); + Object.assign(CoinStorage.collection, mockCollection(null)); + let blockModelRemoveSpy = BlockStorage.collection.deleteMany as sinon.SinonSpy; + let transactionModelRemoveSpy = TransactionStorage.collection.deleteMany as sinon.SinonSpy; + let coinModelRemoveSpy = CoinStorage.collection.deleteMany as sinon.SinonSpy; + let coinModelUpdateSpy = CoinStorage.collection.updateMany as sinon.SinonSpy; const params = { header: { @@ -146,7 +146,7 @@ describe('Block Model', function() { network: 'regtest' }; - await BlockModel.handleReorg(params); + await BlockStorage.handleReorg(params); expect(blockModelRemoveSpy.notCalled).to.be.true; expect(transactionModelRemoveSpy.notCalled).to.be.true; expect(coinModelRemoveSpy.notCalled).to.be.true; @@ -154,10 +154,10 @@ describe('Block Model', function() { }); it('should return if localTip height is zero', async () => { - let blockModelRemoveSpy = BlockModel.collection.deleteMany as sinon.SinonSpy; - let transactionModelRemoveSpy = TransactionModel.collection.deleteMany as sinon.SinonSpy; - let coinModelRemoveSpy = CoinModel.collection.deleteMany as sinon.SinonSpy; - let coinModelUpdateSpy = CoinModel.collection.updateMany as sinon.SinonSpy; + let blockModelRemoveSpy = BlockStorage.collection.deleteMany as sinon.SinonSpy; + let transactionModelRemoveSpy = TransactionStorage.collection.deleteMany as sinon.SinonSpy; + let coinModelRemoveSpy = CoinStorage.collection.deleteMany as sinon.SinonSpy; + let coinModelUpdateSpy = CoinStorage.collection.updateMany as sinon.SinonSpy; let blockMethodParams = { chain: 'BTC', @@ -165,9 +165,9 @@ describe('Block Model', function() { block: TEST_BLOCK, height: 1355 }; - let params = Object.assign(BlockModel, blockMethodParams); + let params = Object.assign(BlockStorage, blockMethodParams); - await BlockModel.handleReorg(params); + await BlockStorage.handleReorg(params); expect(blockModelRemoveSpy.notCalled).to.be.true; expect(transactionModelRemoveSpy.notCalled).to.be.true; expect(coinModelRemoveSpy.notCalled).to.be.true; @@ -185,10 +185,10 @@ describe('Block Model', function() { block: TEST_BLOCK, height: 1355 }; - let params = Object.assign(BlockModel, blockMethodParams); - const removeSpy = BlockModel.collection.deleteMany as sinon.SinonSpy; + let params = Object.assign(BlockStorage, blockMethodParams); + const removeSpy = BlockStorage.collection.deleteMany as sinon.SinonSpy; - await BlockModel.handleReorg(params); + await BlockStorage.handleReorg(params); expect(removeSpy.called).to.be.true; }); @@ -204,10 +204,10 @@ describe('Block Model', function() { block: TEST_BLOCK, height: 1355 }; - let params = Object.assign(BlockModel, blockMethodParams); - const removeSpy = TransactionModel.collection.deleteMany as sinon.SinonSpy; + let params = Object.assign(BlockStorage, blockMethodParams); + const removeSpy = TransactionStorage.collection.deleteMany as sinon.SinonSpy; - await BlockModel.handleReorg(params); + await BlockStorage.handleReorg(params); expect(removeSpy.called).to.be.true; }); @@ -223,11 +223,11 @@ describe('Block Model', function() { block: TEST_BLOCK, height: 1355 }; - let params = Object.assign(BlockModel, blockMethodParams); + let params = Object.assign(BlockStorage, blockMethodParams); const collectionSpy = Storage.db!.collection as sinon.SinonSpy; - const removeSpy = CoinModel.collection.deleteMany as sinon.SinonSpy; + const removeSpy = CoinStorage.collection.deleteMany as sinon.SinonSpy; - await BlockModel.handleReorg(params); + await BlockStorage.handleReorg(params); expect(collectionSpy.calledOnceWith('coins')); expect(removeSpy.callCount).to.eq(3); }); @@ -244,11 +244,11 @@ describe('Block Model', function() { block: TEST_BLOCK, height: 1355 }; - let params = Object.assign(BlockModel, blockMethodParams); + let params = Object.assign(BlockStorage, blockMethodParams); const collectionSpy = Storage.db!.collection as sinon.SinonSpy; - const updateSpy = CoinModel.collection.updateMany as sinon.SinonSpy; + const updateSpy = CoinStorage.collection.updateMany as sinon.SinonSpy; - await BlockModel.handleReorg(params); + await BlockStorage.handleReorg(params); expect(collectionSpy.calledOnceWith('coins')); expect(updateSpy.called).to.be.true; }); @@ -275,7 +275,7 @@ describe('Block Model', function() { processed: true }; - const result = BlockModel._apiTransform(block, { object: true }); + const result = BlockStorage._apiTransform(block, { object: true }); expect(result.hash).to.be.equal(block.hash); expect(result.height).to.be.equal(block.height); diff --git a/packages/bitcore-node/test/unit/models/coin.unit.ts b/packages/bitcore-node/test/unit/models/coin.unit.ts index 85aedb02dfe..8fcff137f21 100644 --- a/packages/bitcore-node/test/unit/models/coin.unit.ts +++ b/packages/bitcore-node/test/unit/models/coin.unit.ts @@ -1,5 +1,5 @@ import { expect } from 'chai'; -import { CoinModel, ICoin } from '../../../src/models/coin'; +import { CoinStorage, ICoin } from '../../../src/models/coin'; import { SpentHeightIndicators } from '../../../src/types/Coin'; import { ObjectId } from 'mongodb'; @@ -23,7 +23,7 @@ describe('Coin Model', function() { spentHeight: SpentHeightIndicators.unspent } as ICoin; - const result = CoinModel._apiTransform(coin, { object: false }); + const result = CoinStorage._apiTransform(coin, { object: false }); const parseResult = JSON.parse(result.toString()); expect(parseResult).to.deep.equal({ @@ -60,7 +60,7 @@ describe('Coin Model', function() { spentHeight: SpentHeightIndicators.unspent } as ICoin; - const result = CoinModel._apiTransform(coin, { object: true }); + const result = CoinStorage._apiTransform(coin, { object: true }); expect(result).to.deep.equal({ _id: id.toHexString(), mintTxid: '81f24ac62a6ffb634b74e6278997f0788f3c64e844453f8831d2a526dc3ecb13', diff --git a/packages/bitcore-node/test/unit/models/wallet.unit.ts b/packages/bitcore-node/test/unit/models/wallet.unit.ts index 4454d33a610..4c52d171ec8 100644 --- a/packages/bitcore-node/test/unit/models/wallet.unit.ts +++ b/packages/bitcore-node/test/unit/models/wallet.unit.ts @@ -1,7 +1,7 @@ import { expect } from 'chai'; import * as sinon from 'sinon'; import { WalletModel, IWallet } from '../../../src/models/wallet'; -import { WalletAddressModel } from '../../../src/models/walletAddress'; +import { WalletAddressStorage } from '../../../src/models/walletAddress'; import { mockCollection } from "../../helpers/index.js"; import { ObjectID } from "bson"; import { MongoBound } from "../../../src/models/base"; @@ -50,8 +50,8 @@ describe('Wallet Model', function () { sandbox.restore(); }); it('should call wallet address model update coins', async () => { - Object.assign(WalletAddressModel.collection, mockCollection([])) - let walletAddressModelSpy = sandbox.stub(WalletAddressModel, 'updateCoins').returns({ + Object.assign(WalletAddressStorage.collection, mockCollection([])) + let walletAddressModelSpy = sandbox.stub(WalletAddressStorage, 'updateCoins').returns({ wallet: sandbox.stub().returnsThis(), addresses: sandbox.stub().returnsThis() }); diff --git a/packages/bitcore-node/test/unit/models/walletAddress.unit.ts b/packages/bitcore-node/test/unit/models/walletAddress.unit.ts index 1799c131bfe..4150422a582 100644 --- a/packages/bitcore-node/test/unit/models/walletAddress.unit.ts +++ b/packages/bitcore-node/test/unit/models/walletAddress.unit.ts @@ -1,5 +1,5 @@ import { expect } from 'chai'; -import { IWalletAddress, WalletAddressModel } from "../../../src/models/walletAddress"; +import { IWalletAddress, WalletAddressStorage } from "../../../src/models/walletAddress"; describe('WalletAddress Model', function () { @@ -9,7 +9,7 @@ describe('WalletAddress Model', function () { address: '2NA2xTdQH6CG73Gc26oQZ7FEmvTx9Kwo7uf', } as IWalletAddress; - const result = WalletAddressModel._apiTransform(walletAddress, { + const result = WalletAddressStorage._apiTransform(walletAddress, { object: false }).toString(); @@ -24,7 +24,7 @@ describe('WalletAddress Model', function () { address: '2NA2xTdQH6CG73Gc26oQZ7FEmvTx9Kwo7uf', } as IWalletAddress; - const result = WalletAddressModel._apiTransform(walletAddress, { + const result = WalletAddressStorage._apiTransform(walletAddress, { object: true }); expect(result).to.deep.equal({ address: '2NA2xTdQH6CG73Gc26oQZ7FEmvTx9Kwo7uf' }); diff --git a/packages/bitcore-node/test/util/verify.ts b/packages/bitcore-node/test/util/verify.ts index 524e646e0ff..b2ce7cadabb 100755 --- a/packages/bitcore-node/test/util/verify.ts +++ b/packages/bitcore-node/test/util/verify.ts @@ -1,11 +1,11 @@ #!/usr/bin/env node -import { BlockModel, IBlock } from '../../src/models/block'; +import { BlockStorage, IBlock } from '../../src/models/block'; import { AsyncRPC } from '../../src/rpc'; import { expect } from 'chai'; -import { TransactionModel, ITransaction } from '../../src/models/transaction'; -import { CoinModel } from '../../src/models/coin'; +import { TransactionStorage, ITransaction } from '../../src/models/transaction'; +import { CoinStorage } from '../../src/models/coin'; import { ChainNetwork } from '../../src/types/ChainNetwork'; -import { WalletAddressModel } from '../../src/models/walletAddress'; +import { WalletAddressStorage } from '../../src/models/walletAddress'; import { Storage } from '../../src/services/storage'; import config from '../../src/config'; import logger from '../../src/logger'; @@ -29,7 +29,7 @@ export async function blocks( const normalizedTimes = new Array(tip.height).fill(0); // check each block - const cursor = BlockModel.collection.find({ + const cursor = BlockStorage.collection.find({ chain: info.chain, network: info.network }); @@ -78,7 +78,7 @@ export async function blocks( expect(block.reward, 'block reward').to.equal(Math.round(reward * SATOSHI)); // Check block only has all `truth`'s transactions - const ours = await TransactionModel.collection + const ours = await TransactionStorage.collection .find({ chain: info.chain, network: info.network, @@ -122,7 +122,7 @@ export async function blocks( } // Check no other tx points to our block hash - const extra = await TransactionModel.collection + const extra = await TransactionStorage.collection .find({ chain: info.chain, network: info.network, @@ -155,7 +155,7 @@ export async function transactions( ) { const rpc = new AsyncRPC(creds.username, creds.password, creds.host, creds.port); - const txcursor = TransactionModel.collection.find({ + const txcursor = TransactionStorage.collection.find({ chain: info.chain, network: info.network }); @@ -175,7 +175,7 @@ export async function transactions( { // Minted by this transaction - const ours = await CoinModel.collection + const ours = await CoinStorage.collection .find({ network: info.network, chain: info.chain, @@ -196,7 +196,7 @@ export async function transactions( // wallets expect(tx.wallets).to.include.members(Array.from(our.wallets)); if (our.wallets.length > 0) { - const wallets = await WalletAddressModel.collection + const wallets = await WalletAddressStorage.collection .find({ wallet: { $in: our.wallets @@ -213,7 +213,7 @@ export async function transactions( { // Spent by this transaction - const ours = await CoinModel.collection + const ours = await CoinStorage.collection .find({ network: info.network, chain: info.chain, From b109cd9dfe0fcce1387cb80ffe15905f55b1774e Mon Sep 17 00:00:00 2001 From: Micah Riggan Date: Thu, 27 Dec 2018 11:19:35 -0500 Subject: [PATCH 7/9] Fixing bug --- packages/bitcore-node/src/services/p2p.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/bitcore-node/src/services/p2p.ts b/packages/bitcore-node/src/services/p2p.ts index 1614ebb3ee8..13a32d34157 100644 --- a/packages/bitcore-node/src/services/p2p.ts +++ b/packages/bitcore-node/src/services/p2p.ts @@ -34,11 +34,11 @@ export class P2pManager { logger.info('Starting P2P Manager'); const p2pWorkers = new Array(); for (let chainNetwork of Config.chainNetworks()) { + const { chain, network } = chainNetwork; const chainConfig = Config.chainConfig(chainNetwork); if (chainConfig.chainSource && chainConfig.chainSource !== 'p2p') { continue; } - const { chain, network } = chainConfig; const p2pWorker = new P2pWorker({ chain, network, From 12837901bb6769347659148387f79894e7d5cfa7 Mon Sep 17 00:00:00 2001 From: Micah Riggan Date: Thu, 27 Dec 2018 11:22:35 -0500 Subject: [PATCH 8/9] Renaming WalletModel to WalletStorage --- packages/bitcore-node/src/models/wallet.ts | 4 ++-- .../src/providers/chain-state/internal/internal.ts | 8 ++++---- packages/bitcore-node/test/helpers/index.ts | 4 ++-- packages/bitcore-node/test/unit/models/wallet.unit.ts | 8 ++++---- 4 files changed, 12 insertions(+), 12 deletions(-) diff --git a/packages/bitcore-node/src/models/wallet.ts b/packages/bitcore-node/src/models/wallet.ts index 94f417276eb..3e6fc1baeb0 100644 --- a/packages/bitcore-node/src/models/wallet.ts +++ b/packages/bitcore-node/src/models/wallet.ts @@ -14,7 +14,7 @@ export type IWallet = { path: string; }; -export class WalletSchema extends BaseModel { +export class WalletModel extends BaseModel { constructor(storage?: StorageService) { super('wallets', storage); } @@ -42,4 +42,4 @@ export class WalletSchema extends BaseModel { } } -export let WalletModel = new WalletSchema(); +export let WalletStorage = new WalletModel(); diff --git a/packages/bitcore-node/src/providers/chain-state/internal/internal.ts b/packages/bitcore-node/src/providers/chain-state/internal/internal.ts index 08e460698b1..57399f8deea 100644 --- a/packages/bitcore-node/src/providers/chain-state/internal/internal.ts +++ b/packages/bitcore-node/src/providers/chain-state/internal/internal.ts @@ -5,7 +5,7 @@ import { MongoBound } from '../../../models/base'; import { ObjectId } from 'mongodb'; import { CoinStorage, ICoin } from '../../../models/coin'; import { BlockStorage, IBlock } from '../../../models/block'; -import { WalletModel, IWallet } from '../../../models/wallet'; +import { WalletStorage, IWallet } from '../../../models/wallet'; import { WalletAddressStorage } from '../../../models/walletAddress'; import { CSP } from '../../../types/namespaces/ChainStateProvider'; import { Storage } from '../../../services/storage'; @@ -241,13 +241,13 @@ export class InternalStateProvider implements CSP.IChainStateService { path, singleAddress }; - await WalletModel.collection.insertOne(wallet); + await WalletStorage.collection.insertOne(wallet); return wallet; } async getWallet(params: CSP.GetWalletParams) { const { pubKey } = params; - return WalletModel.collection.findOne({ pubKey }); + return WalletStorage.collection.findOne({ pubKey }); } streamWalletAddresses(params: CSP.StreamWalletAddressesParams) { @@ -258,7 +258,7 @@ export class InternalStateProvider implements CSP.IChainStateService { async streamMissingWalletAddresses(params: CSP.StreamWalletMissingAddressesParams) { const { chain, network, pubKey, res } = params; - const wallet = await WalletModel.collection.findOne({ pubKey }); + const wallet = await WalletStorage.collection.findOne({ pubKey }); const walletId = wallet!._id!; const query = { chain, network, wallets: walletId, spentHeight: { $gte: SpentHeightIndicators.minimum } }; const cursor = CoinStorage.collection.find(query).addCursorFlag('noCursorTimeout', true); diff --git a/packages/bitcore-node/test/helpers/index.ts b/packages/bitcore-node/test/helpers/index.ts index 05cae6e7f9c..8d6df683aa7 100644 --- a/packages/bitcore-node/test/helpers/index.ts +++ b/packages/bitcore-node/test/helpers/index.ts @@ -3,7 +3,7 @@ import { BlockStorage } from '../../src/models/block'; import { TransactionStorage } from '../../src/models/transaction'; import { CoinStorage } from '../../src/models/coin'; import { WalletAddressStorage } from '../../src/models/walletAddress'; -import { WalletModel } from '../../src/models/wallet'; +import { WalletStorage } from '../../src/models/wallet'; import { Storage } from '../../src/services/storage'; import { BaseModel } from '../../src/models/base'; @@ -12,7 +12,7 @@ export async function resetDatabase() { await resetModel(TransactionStorage); await resetModel(CoinStorage); await resetModel(WalletAddressStorage); - await resetModel(WalletModel); + await resetModel(WalletStorage); } export async function resetModel(model: BaseModel) { diff --git a/packages/bitcore-node/test/unit/models/wallet.unit.ts b/packages/bitcore-node/test/unit/models/wallet.unit.ts index 4c52d171ec8..b4cf8a31b80 100644 --- a/packages/bitcore-node/test/unit/models/wallet.unit.ts +++ b/packages/bitcore-node/test/unit/models/wallet.unit.ts @@ -1,6 +1,6 @@ import { expect } from 'chai'; import * as sinon from 'sinon'; -import { WalletModel, IWallet } from '../../../src/models/wallet'; +import { WalletStorage, IWallet } from '../../../src/models/wallet'; import { WalletAddressStorage } from '../../../src/models/walletAddress'; import { mockCollection } from "../../helpers/index.js"; import { ObjectID } from "bson"; @@ -16,7 +16,7 @@ describe('Wallet Model', function () { pubKey: 'xpub661MyMwAqRbcFa63vSTa3vmRiVWbpLWhgUsyvjfMFP7ePR5osC1rtPUkgJrB94V1YEQathfWLm9U5zaZttYPDPWhASwJGUvYvPGtofqnTGN', path: 'm/44\'/0\'/0\'' } as IWallet; - const result = WalletModel._apiTransform(wallet, { object: false }); + const result = WalletStorage._apiTransform(wallet, { object: false }); const parseResult = JSON.parse(result.toString()); expect(parseResult).to.deep.equal({ @@ -32,7 +32,7 @@ describe('Wallet Model', function () { pubKey: 'xpub661MyMwAqRbcFa63vSTa3vmRiVWbpLWhgUsyvjfMFP7ePR5osC1rtPUkgJrB94V1YEQathfWLm9U5zaZttYPDPWhASwJGUvYvPGtofqnTGN', path: 'm/44\'/0\'/0\'' } as IWallet; - const result = WalletModel._apiTransform(wallet, { object: true }); + const result = WalletStorage._apiTransform(wallet, { object: true }); expect(result).to.deep.equal({ name: 'Wallet1', pubKey: 'xpub661MyMwAqRbcFa63vSTa3vmRiVWbpLWhgUsyvjfMFP7ePR5osC1rtPUkgJrB94V1YEQathfWLm9U5zaZttYPDPWhASwJGUvYvPGtofqnTGN' @@ -66,7 +66,7 @@ describe('Wallet Model', function () { network: 'regtest' } as MongoBound; - await WalletModel.updateCoins(wallet); + await WalletStorage.updateCoins(wallet); expect(walletAddressModelSpy.calledOnce).to.be.true; }); From ac395a59a39d38da25c3b083ab0635d12f5b6227 Mon Sep 17 00:00:00 2001 From: Micah Riggan Date: Thu, 27 Dec 2018 11:30:27 -0500 Subject: [PATCH 9/9] wireup when storage is already connected --- packages/bitcore-node/src/server.ts | 2 +- packages/bitcore-node/src/services/event.ts | 8 ++++++-- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/packages/bitcore-node/src/server.ts b/packages/bitcore-node/src/server.ts index 9b383015a0a..9e9b3d6dae0 100755 --- a/packages/bitcore-node/src/server.ts +++ b/packages/bitcore-node/src/server.ts @@ -31,7 +31,7 @@ const runWorker = async () => { }; const start = async () => { - await Storage.start({}); + await Storage.start(); Event.start(); if (cluster.isMaster) { await runMaster(); diff --git a/packages/bitcore-node/src/services/event.ts b/packages/bitcore-node/src/services/event.ts index 8322ace5dd3..4df9c2f3dbf 100644 --- a/packages/bitcore-node/src/services/event.ts +++ b/packages/bitcore-node/src/services/event.ts @@ -31,9 +31,13 @@ export class EventService { } logger.info('Starting Event Service'); this.stopped = false; - this.storageService.connection.on('CONNECTED', () => { + if (this.storageService.connected) { this.wireup(); - }); + } else { + this.storageService.connection.on('CONNECTED', () => { + this.wireup(); + }); + } } stop() {