Пример #1
0
    def get_connection_to_forward(self, metadata):
        """ Override ProxyConnection.get_connection_to_forward()
        """
        if metadata.cluster_peer_id == 0:
            # RPC from master
            return None

        shard = self.shards.get(metadata.branch, None)
        if not shard:
            self.close_with_error("incorrect forwarding branch")
            return

        peer_shard_conn = shard.peers.get(metadata.cluster_peer_id, None)
        if peer_shard_conn is None:
            # Master can close the peer connection at any time
            # TODO: any way to avoid this race?
            Logger.warning_every_sec(
                "cannot find peer shard conn for cluster id {}".format(
                    metadata.cluster_peer_id
                ),
                1,
            )
            return NULL_CONNECTION

        return peer_shard_conn.get_forwarding_connection()
Пример #2
0
    def get_connection_to_forward(self, metadata):
        """ Override ProxyConnection.get_connection_to_forward()
        """
        if metadata.cluster_peer_id == 0:
            # RPC from master
            return None

        if (metadata.branch.get_full_shard_id()
                not in self.env.quark_chain_config.get_full_shard_ids()):
            self.close_with_error("incorrect forwarding branch {}".format(
                metadata.branch.to_str()))

        shard = self.shards.get(metadata.branch, None)
        if not shard:
            # shard has not been created yet
            return NULL_CONNECTION

        peer_shard_conn = shard.peers.get(metadata.cluster_peer_id, None)
        if peer_shard_conn is None:
            # Master can close the peer connection at any time
            # TODO: any way to avoid this race?
            Logger.warning_every_sec(
                "cannot find peer shard conn for cluster id {}".format(
                    metadata.cluster_peer_id),
                1,
            )
            return NULL_CONNECTION

        return peer_shard_conn.get_forwarding_connection()
Пример #3
0
    async def add_block(self, block):
        """ Returns true if block is successfully added. False on any error.
        called by 1. local miner (will not run if syncing) 2. SyncTask
        """
        old_tip = self.state.header_tip
        try:
            xshard_list = self.state.add_block(block)
        except Exception as e:
            Logger.error_exception()
            return False

        # only remove from pool if the block successfully added to state,
        #   this may cache failed blocks but prevents them being broadcasted more than needed
        # TODO add ttl to blocks in new_block_pool
        self.state.new_block_pool.pop(block.header.get_hash(), None)
        # block has been added to local state, broadcast tip so that peers can sync if needed
        try:
            if old_tip != self.state.header_tip:
                self.broadcast_new_tip()
        except Exception:
            Logger.warning_every_sec("broadcast tip failure", 1)

        # block already existed in local shard state
        # but might not have been propagated to other shards and master
        # let's make sure all the shards and master got it before return
        if xshard_list is None:
            future = self.add_block_futures.get(block.header.get_hash(), None)
            if future:
                Logger.info(
                    "[{}] {} is being added ... waiting for it to finish".
                    format(block.header.branch.get_shard_id(),
                           block.header.height))
                await future
            return True

        self.add_block_futures[
            block.header.get_hash()] = self.loop.create_future()

        # Start mining new one before propagating inside cluster
        # The propagation should be done by the time the new block is mined
        self.miner.mine_new_block_async()
        prev_root_height = self.state.db.get_root_block_by_hash(
            block.header.hash_prev_root_block).header.height
        await self.slave.broadcast_xshard_tx_list(block, xshard_list,
                                                  prev_root_height)
        await self.slave.send_minor_block_header_to_master(
            block.header,
            len(block.tx_list),
            len(xshard_list),
            self.state.get_shard_stats(),
        )

        self.add_block_futures[block.header.get_hash()].set_result(None)
        del self.add_block_futures[block.header.get_hash()]
        return True
Пример #4
0
    async def add_block(self, block):
        """ Returns true if block is successfully added. False on any error.
        called by 1. local miner (will not run if syncing) 2. SyncTask
        """

        block_hash = block.header.get_hash()
        commit_status, future = self.__get_block_commit_status_by_hash(
            block_hash)
        if commit_status == BLOCK_COMMITTED:
            return True
        elif commit_status == BLOCK_COMMITTING:
            Logger.info(
                "[{}] {} is being added ... waiting for it to finish".format(
                    block.header.branch.to_str(), block.header.height))
            await future
            return True

        check(commit_status == BLOCK_UNCOMMITTED)
        # Validate and add the block
        old_tip = self.state.header_tip
        try:
            xshard_list, coinbase_amount_map = self.state.add_block(block,
                                                                    force=True)
        except Exception as e:
            Logger.error_exception()
            return False

        # only remove from pool if the block successfully added to state,
        # this may cache failed blocks but prevents them being broadcasted more than needed
        # TODO add ttl to blocks in new_block_header_pool
        self.state.new_block_header_pool.pop(block_hash, None)
        # block has been added to local state, broadcast tip so that peers can sync if needed
        try:
            if old_tip != self.state.header_tip:
                self.broadcast_new_tip()
        except Exception:
            Logger.warning_every_sec("broadcast tip failure", 1)

        # Add the block in future and wait
        self.add_block_futures[block_hash] = self.loop.create_future()

        prev_root_height = self.state.db.get_root_block_header_by_hash(
            block.header.hash_prev_root_block).height
        await self.slave.broadcast_xshard_tx_list(block, xshard_list,
                                                  prev_root_height)
        await self.slave.send_minor_block_header_to_master(
            block.header,
            len(block.tx_list),
            len(xshard_list),
            coinbase_amount_map,
            self.state.get_shard_stats(),
        )

        # Commit the block
        self.state.commit_by_hash(block_hash)
        Logger.debug("committed mblock {}".format(block_hash.hex()))

        # Notify the rest
        self.add_block_futures[block_hash].set_result(None)
        del self.add_block_futures[block_hash]
        return True