UNPKG

int-cli

Version:

INT is the new generation of bottom-up created system of IoT and blockchain

162 lines (161 loc) 6.9 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); const core_1 = require("../../core"); const storage_1 = require("./storage"); const util_1 = require("util"); const path = require("path"); class ChainEventServer { constructor(options) { this.m_syncing = false; this.m_chain = options.chain; this.m_logger = options.chain.logger; const dbPath = path.join(this.m_chain.dataDir, 'events'); this.m_storage = new storage_1.ChainEventStorage({ logger: this.m_logger, dbPath, eventDefinations: options.chain.handler.getEventDefinations() }); } async init(options) { const readonly = util_1.isNullOrUndefined(options.readonly) ? false : options.readonly; const sir = await this.m_storage.init({ readonly }); if (readonly || (sir.err && sir.err !== core_1.ErrorCode.RESULT_NOT_FOUND)) { return sir.err; } if (sir.err === core_1.ErrorCode.RESULT_NOT_FOUND) { const ghr = await this.m_chain.getHeader(0); if (ghr.err) { this.m_logger.error(`event server init failed for get genesis header failed ${core_1.stringifyErrorCode(ghr.err)}`); return ghr.err; } const genesis = await this.m_chain.getBlock(ghr.header.hash); if (!genesis) { this.m_logger.error(`event server init failed for get genesis failed`); return core_1.ErrorCode.RESULT_EXCEPTION; } let err = await this.m_storage.addBlock(genesis); if (err) { this.m_logger.error(`event server init failed for add genesis to storage failed ${core_1.stringifyErrorCode(err)}`); return err; } } this._syncEvents(); this.m_chain.on('tipBlock', () => { this._syncEvents(); }); return core_1.ErrorCode.RESULT_OK; } async _syncEvents() { if (this.m_syncing) { return; } this.m_syncing = true; this.m_logger.info(`begin sync events`); while (true) { const lbr = await this.m_storage.getLatestBlock(); if (lbr.err) { this.m_logger.error(`event server sync failed for get latest block from storage ${core_1.stringifyErrorCode(lbr.err)}`); break; } const ghr = await this.m_chain.getHeader(lbr.latest.number + 1); if (ghr.err) { if (ghr.err === core_1.ErrorCode.RESULT_NOT_FOUND) { this.m_logger.info(`event server sync ignored for no more block`); } else { this.m_logger.error(`event server sync failed for get header from chain ${core_1.stringifyErrorCode(ghr.err)}`); } break; } if (ghr.header.preBlockHash === lbr.latest.hash) { const block = await this.m_chain.getBlock(ghr.header.hash); if (!block) { this.m_logger.error(`event server sync for get block ${ghr.header.hash} failed`); break; } this.m_logger.info(`begin add events block ${block.number} ${block.hash}`); let err = await this.m_storage.addBlock(block); if (err) { this.m_logger.error(`event server sync failed for add block ${block.hash} to storage failed ${core_1.stringifyErrorCode(err)}`); break; } } else { let _ghr = await this.m_chain.getHeader(lbr.latest.hash); if (_ghr.err) { this.m_logger.error(`event server sync failed for get header ${lbr.latest.hash} from chain failed ${core_1.stringifyErrorCode(_ghr.err)}`); break; } let forkFrom = _ghr.header; let _err = core_1.ErrorCode.RESULT_OK; while (true) { _ghr = await this.m_chain.getHeader(forkFrom.number - 1); if (_ghr.err) { this.m_logger.error(`event server sync failed for get header ${forkFrom.number - 1} from chain failed ${core_1.stringifyErrorCode(_ghr.err)}`); _err = _ghr.err; break; } if (_ghr.header.hash === forkFrom.preBlockHash) { break; } forkFrom = _ghr.header; } if (_err) { break; } _err = await this.m_storage.revertToBlock(forkFrom.number - 1); if (_err) { break; } } } this.m_logger.info(`finish sync events`); this.m_syncing = false; } async getEventByStub(block, stub) { let ghr; if (util_1.isString(block)) { ghr = await this.m_chain.getHeader(block); } else if (util_1.isObject(block)) { ghr = await this.m_chain.getHeader(block.from, block.offset); } else { return { err: core_1.ErrorCode.RESULT_INVALID_PARAM }; } if (ghr.err) { this.m_logger.error(`get event by stub failed for get headers failed `, core_1.stringifyErrorCode(ghr.err)); return { err: ghr.err }; } let blocks = []; for (const header of ghr.headers) { let _block = this.m_chain.getBlock(header.hash); if (!_block) { this.m_logger.error(`get event by stub failed for block ${header.hash} missing`); return { err: core_1.ErrorCode.RESULT_INVALID_BLOCK }; } blocks.push(_block); } const ger = await this.m_storage.getEvents({ blocks: blocks.map((_block) => _block.hash), querySql: stub.querySql }); if (ger.err) { this.m_logger.error(`get event by stub failed for storage err `, core_1.stringifyErrorCode(ger.err)); return { err: ger.err }; } let events = []; for (const _block of blocks) { if (ger.events.has(_block.hash)) { const blockEvents = _block.content.eventLogs; const indices = ger.events.get(_block.hash); let eventLogs = []; for (const index of indices) { eventLogs.push(blockEvents[index]); } events.push({ blockHash: _block.hash, blockNumber: _block.number, eventLogs }); } } return { err: core_1.ErrorCode.RESULT_OK, events }; } } exports.ChainEventServer = ChainEventServer;