UNPKG

int-cli

Version:

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

177 lines (176 loc) 7.14 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); const assert = require("assert"); const error_code_1 = require("../error_code"); const chain_1 = require("../chain"); const transaction_1 = require("./transaction"); class BlockExecutor { constructor(options) { this.m_storage = options.storage; this.m_handler = options.handler; this.m_block = options.block; this.m_externContext = options.externContext; this.m_logger = options.logger; this.m_externParams = options.externParams.slice(0); Object.defineProperty(this.m_externContext, 'logger', { writable: false, value: this.m_logger }); this.m_globalOptions = options.globalOptions; } finalize() { for (const ep of this.m_externParams) { ep.finalize(); } } get externContext() { return this.m_externContext; } _newTransactionExecutor(l, tx) { return new transaction_1.TransactionExecutor(this.m_handler, l, tx, this.m_logger); } _newEventExecutor(l) { return new transaction_1.EventExecutor(this.m_handler, l, this.m_logger); } async execute() { let t1 = Date.now(); let ret = await this._execute(this.m_block); let t2 = Date.now(); this.m_logger.info(`runblock time====${t2 - t1}, count=${this.m_block.content.transactions.length}`); return ret; } async verify() { let oldBlock = this.m_block; this.m_block = this.m_block.clone(); let err = await this.execute(); if (err) { if (err === error_code_1.ErrorCode.RESULT_TX_CHECKER_ERROR) { return { err: error_code_1.ErrorCode.RESULT_OK, valid: error_code_1.ErrorCode.RESULT_TX_CHECKER_ERROR }; } else { return { err }; } } if (this.m_block.hash !== oldBlock.hash) { this.m_logger.error(`block ${oldBlock.number} hash mismatch!! except storage hash ${oldBlock.header.storageHash}, actual ${this.m_block.header.storageHash} except hash ${oldBlock.hash}, actual ${this.m_block.hash} `); } if (this.m_block.hash === oldBlock.hash) { return { err: error_code_1.ErrorCode.RESULT_OK, valid: error_code_1.ErrorCode.RESULT_OK }; } else { return { err: error_code_1.ErrorCode.RESULT_OK, valid: error_code_1.ErrorCode.RESULT_VERIFY_NOT_MATCH }; } } async _execute(block) { this.m_logger.info(`begin execute block ${block.number}`); let receipts = []; let ebr = await this.executePreBlockEvent(); if (ebr.err) { this.m_logger.error(`blockexecutor execute begin_event failed,errcode=${ebr.err},blockhash=${block.hash}`); return ebr.err; } receipts.push(...ebr.receipts); ebr = await this._executeTransactions(); if (ebr.err) { this.m_logger.error(`blockexecutor execute method failed,errcode=${ebr.err},blockhash=${block.hash}`); return ebr.err; } receipts.push(...ebr.receipts); ebr = await this.executePostBlockEvent(); if (ebr.err) { this.m_logger.error(`blockexecutor execute end_event failed,errcode=${ebr.err},blockhash=${block.hash}`); return ebr.err; } receipts.push(...ebr.receipts); // 票据 block.content.setReceipts(receipts); // 更新块信息 return await this._updateBlock(block); } async executeBlockEvent(listener) { let exec = this._newEventExecutor(listener); let ret = await exec.execute(this.m_block.header, this.m_storage, this.m_externContext); if (ret.err) { this.m_logger.error(`block event execute failed`); } return ret; } async executePreBlockEvent() { if (this.m_block.number === 0) { // call initialize if (this.m_handler.genesisListener) { const eber = await this.executeBlockEvent(this.m_handler.genesisListener); if (eber.err || eber.receipt.returnCode) { this.m_logger.error(`handler's genesisListener execute failed`); return { err: error_code_1.ErrorCode.RESULT_EXCEPTION }; } } } let receipts = []; let listeners = await this.m_handler.getPreBlockListeners(this.m_block.number); for (const l of listeners) { const eber = await this.executeBlockEvent(l.listener); if (eber.err) { return { err: eber.err }; } eber.receipt.setSource({ sourceType: chain_1.ReceiptSourceType.preBlockEvent, eventIndex: l.index }); receipts.push(eber.receipt); } return { err: error_code_1.ErrorCode.RESULT_OK, receipts }; } async executePostBlockEvent() { let receipts = []; let listeners = await this.m_handler.getPostBlockListeners(this.m_block.number); for (const l of listeners) { const eber = await this.executeBlockEvent(l.listener); if (eber.err) { return { err: eber.err }; } eber.receipt.setSource({ sourceType: chain_1.ReceiptSourceType.postBlockEvent, eventIndex: l.index }); receipts.push(eber.receipt); } return { err: error_code_1.ErrorCode.RESULT_OK, receipts }; } async _executeTransactions() { let receipts = []; // 执行tx for (let tx of this.m_block.content.transactions) { const ret = await this.executeTransaction(tx); if (ret.err) { return { err: ret.err }; } receipts.push(ret.receipt); } return { err: error_code_1.ErrorCode.RESULT_OK, receipts }; } async executeTransaction(tx, flag) { const checker = this.m_handler.getTxPendingChecker(tx.method); if (!checker || checker(tx)) { this.m_logger.error(`verfiy block failed for tx ${tx.hash} ${tx.method} checker failed`); return { err: error_code_1.ErrorCode.RESULT_TX_CHECKER_ERROR }; } let listener = this.m_handler.getTxListener(tx.method); assert(listener, `no listener for ${tx.method}`); if (!listener) { return { err: error_code_1.ErrorCode.RESULT_NOT_SUPPORT }; } let exec = this._newTransactionExecutor(listener, tx); let ret = await exec.execute(this.m_block.header, this.m_storage, this.m_externContext, flag); return ret; } async _updateBlock(block) { // 写回数据库签名 const mdr = await this.m_storage.messageDigest(); if (mdr.err) { return mdr.err; } block.header.storageHash = mdr.value; block.header.updateContent(block.content); block.header.updateHash(); return error_code_1.ErrorCode.RESULT_OK; } } exports.BlockExecutor = BlockExecutor;