Home Reference Source Test

src/main/generic/consensus/pico/PicoConsensusAgent.js

class PicoConsensusAgent extends BaseMiniConsensusAgent {
    /**
     * @param {PicoConsensus} consensus
     * @param {Peer} peer
     * @param {Subscription} targetSubscription
     */
    constructor(consensus, peer, targetSubscription) {
        super(consensus.blockchain, consensus.mempool, consensus.network.time, peer, consensus.invRequestManager, targetSubscription);
        this._consensus = consensus;
    }

    /**
     * @param {Hash} hash
     * @param {Block} block
     * @returns {Promise.<void>}
     * @protected
     * @override
     */
    async _processBlock(hash, block) {
        if (this._peer.headHash.equals(hash)) {
            const result = await this._blockchain.pushBlock(block);
            if (result === PicoChain.ERR_INVALID) {
                this._peer.channel.close(CloseType.INVALID_BLOCK, 'received invalid block');
            } else if (result === PicoChain.ERR_INCONSISTENT) {
                this.fire('consensus-failed');
            } else if (this._syncing) {
                this._syncFinished();
            }
        } else {
            if (await this._blockchain.pushBlock(block) === PicoChain.ERR_INVALID) {
                this._peer.channel.close(CloseType.INVALID_BLOCK, 'received invalid block');
            }
        }
    }

    async syncBlockchain() {
        this._syncing = true;

        const headBlock = await this._getBlock(this._peer.headHash, /*includeForks*/ true);
        if (!headBlock) {
            try {
                const hash = this._peer.headHash;
                const block = await this.requestBlock(hash);
                await this._processBlock(hash, block);
            } catch (e) {
                this._peer.channel.close(CloseType.ABORTED_SYNC, 'aborted sync');
            }
        } else {
            this._syncFinished();
        }
    }

    /**
     * @returns {void}
     * @private
     */
    _syncFinished() {
        this._syncing = false;
        this._synced = true;

        this.requestMempool();

        this.fire('sync');
    }

    /**
     * @param {Hash} hash
     * @param {Transaction} transaction
     * @returns {Promise.<void>}
     * @protected
     * @override
     */
    async _processTransaction(hash, transaction) {
        await this._consensus.mempool.pushTransaction(transaction);
    }

    /**
     *
     * @param {Hash} hash
     * @param {boolean} [includeForks = false]
     * @param {boolean} [includeBody = false]
     * @returns {Promise.<?Block>}
     * @protected
     * @override
     */
    _getBlock(hash, includeForks = false, includeBody = false) {
        return this._blockchain.getBlock(hash, includeForks, includeBody);
    }

    /**
     * @param {Hash} hash
     * @param {boolean} [includeForks = false]
     * @returns {Promise.<?Uint8Array>}
     * @protected
     * @override
     */
    _getRawBlock(hash, includeForks = false) {
        return this._blockchain.getRawBlock(hash, includeForks);
    }

    /**
     * @param {Hash} hash
     * @returns {Transaction}
     * @protected
     * @override
     */
    _getTransaction(hash) {
        return this._consensus.mempool.getTransaction(hash);
    }
}

Class.register(PicoConsensusAgent);