UNPKG

bitcore-node

Version:

A blockchain indexing node with extended capabilities using bitcore

129 lines (111 loc) 3.61 kB
import logger from '../../../logger'; import { ErrorType, IVerificationPeer } from '../../../services/verification'; import { XrpBlockStorage } from '../models/block'; import { XrpP2pWorker } from '../p2p'; import { IXrpCoin, IXrpTransaction } from '../types'; export class XrpVerificationPeer extends XrpP2pWorker implements IVerificationPeer { prevBlockNum = 0; prevHash = ''; nextBlockHash = ''; deepScan = false; enableDeepScan() { this.deepScan = true; } disableDeepScan() { this.deepScan = false; } async setupListeners() { this.events.on('connected', async () => { this.client!.on('ledger', async block => { const transformedBlock = this.provider.transformLedger(block, this.network); this.events.emit('block', transformedBlock); }); }); } async resync(start: number, end: number) { const { chain, network } = this; const client = await this.provider.getClient(this.network); let currentHeight = Math.max(1, start); while (currentHeight <= end) { let lastLog = Date.now(); const block = await client.getLedger({ ledgerVersion: currentHeight, includeTransactions: true, includeAllData: true }); const transformedBlock = this.provider.transformLedger(block, network); const nextBlock = await XrpBlockStorage.collection.findOne({ chain, network, previousBlockHash: transformedBlock.hash }); const coinsAndTxs = (block.transactions || []) .map((tx: any) => ({ tx: this.provider.transform(tx, network, transformedBlock), coins: this.provider.transformToCoins(tx, network) })) .filter(data => { return 'txid' in data.tx && data.tx.txid != null; }) as Array<{ tx: IXrpTransaction; coins: Array<IXrpCoin> }>; const blockTxs = new Array<IXrpTransaction>(); const blockCoins = new Array<IXrpCoin>(); for (const coinAndTx of coinsAndTxs) { const { transaction, coins } = await this.provider.tag(chain, network, coinAndTx.tx, coinAndTx.coins); if (this.chainConfig.walletOnlySync && !transaction.wallets.length) { continue; } blockTxs.push(transaction); blockCoins.push(...(coins as Array<IXrpCoin>)); } if (nextBlock) { transformedBlock.nextBlockHash = nextBlock.hash; } await this.blockModel.processBlock({ chain, network, block: transformedBlock, transactions: blockTxs, coins: blockCoins, initialSyncComplete: true }); currentHeight++; if (Date.now() - lastLog > 100) { logger.info('Re-Sync: %o', { chain, network, height: currentHeight }); lastLog = Date.now(); } } } async getBlockForNumber(blockNum: number) { return this.getBlock(blockNum); } async validateDataForBlock(blockNum: number, _: number, log = false) { let success = true; const { chain, network } = this; const errors = new Array<ErrorType>(); const block = await this.blockModel.collection.findOne({ chain, network, height: blockNum, processed: true }); if (!block) { success = false; const error = { model: 'block', err: true, type: 'MISSING_BLOCK', payload: { blockNum } }; errors.push(error); if (log) { console.log(JSON.stringify(error)); } return { success, errors }; } return { success, errors }; } }