def broadcast_block(self, block: Block): # logger.info('<<<Transmitting block: ', block.headerhash) data = qrl_pb2.MR() data.stake_selector = block.transactions[0].addr_from data.block_number = block.block_number data.prev_headerhash = bytes(block.prev_headerhash) if block.block_number > 1: data.reveal_hash = block.reveal_hash self.register_and_broadcast('BK', block.headerhash, block.to_json(), data)
def SFM(self, data): # Send full message """ Send Full Message This function serves the request made for the full message. :return: """ mr_data = qrl_pb2.MR() Parse(data, mr_data) msg_hash = mr_data.hash msg_type = mr_data.type if not self.factory.master_mr.contains(msg_hash, msg_type): return # Sending message from node, doesn't guarantee that peer has received it. # Thus requesting peer could re request it, may be ACK would be required self.transport.write( self.wrap_message(msg_type, self.factory.master_mr.hash_msg[msg_hash].msg))
def broadcast(self, msg_hash: bytes, msg_type, data=None): # Move to factory """ Broadcast This function sends the Message Receipt to all connected peers. :return: """ ignore_peers = [] if msg_hash in self.master_mr.requested_hash: ignore_peers = self.master_mr.requested_hash[msg_hash].peers_connection_list if not data: data = qrl_pb2.MR() data.hash = msg_hash data.type = msg_type for peer in self.peer_connections: if peer not in ignore_peers: peer.transport.write(self.protocol.wrap_message('MR', MessageToJson(data)))
def select_best_bkmr(self): # FIXME: This seems to be a much higher level behavior blocknumber = self.bkmr_blocknumber try: dscore, dhash = self.bkmr_priorityq.get_nowait() if blocknumber <= self.buffered_chain.height: oldscore = self.buffered_chain.get_block_score(blocknumber) if dscore > oldscore: del self.bkmr_priorityq self.bkmr_priorityq = queue.PriorityQueue() return data = qrl_pb2.MR() data.hash = dhash data.type = 'BK' self.RFM(data) self.bkmr_processor = reactor.callLater(5, self.select_best_bkmr) except queue.Empty: return except Exception as e: logger.error('select_best_bkmr Unexpected Exception') logger.error('%s', e)
def MR(self, data): """ Message Receipt This function accepts message receipt from peer, checks if the message hash already been received or not. In case its a already received message, it is ignored. Otherwise the request is made to get the full message. :return: """ mr_data = qrl_pb2.MR() try: Parse(data, mr_data) except Exception as e: # Disconnect peer not following protocol logger.debug( 'Disconnected peer %s not following protocol in MR %s', self.conn_identity, e) self.transport.loseConnection() msg_hash = mr_data.hash if mr_data.type not in MessageReceipt.allowed_types: return if mr_data.type in [ 'TX' ] and self.factory.sync_state.state != ESyncState.synced: return if mr_data.type == 'TX': if len(self.factory.buffered_chain.tx_pool.pending_tx_pool ) >= config.dev.transaction_pool_size: logger.warning( 'TX pool size full, incoming tx dropped. mr hash: %s', bin2hstr(msg_hash)) return if mr_data.type == 'ST' or mr_data.type == 'VT': if self.factory.buffered_chain.height > 1 and self.factory.sync_state.state != ESyncState.synced: return if self.factory.master_mr.contains(msg_hash, mr_data.type): return self.factory.master_mr.add_peer(msg_hash, mr_data.type, self, mr_data) if self.factory.master_mr.is_callLater_active( msg_hash): # Ignore if already requested return if mr_data.type == 'BK': block_chain_buffer = self.factory.buffered_chain if not block_chain_buffer.verify_BK_hash(mr_data, self.conn_identity): if block_chain_buffer.is_duplicate_block( block_idx=mr_data.block_number, prev_headerhash=mr_data.prev_headerhash, stake_selector=mr_data.stake_selector): self.factory.RFM(mr_data) return blocknumber = mr_data.block_number target_blocknumber = block_chain_buffer.bkmr_tracking_blocknumber( self.factory.ntp) if target_blocknumber != self.factory.bkmr_blocknumber: self.factory.bkmr_blocknumber = target_blocknumber del self.factory.bkmr_priorityq self.factory.bkmr_priorityq = PriorityQueue() if blocknumber != target_blocknumber or blocknumber == 1: self.factory.RFM(mr_data) return score = block_chain_buffer.score_BK_hash(mr_data) self.factory.bkmr_priorityq.put((score, msg_hash)) if not self.factory.bkmr_processor.active(): self.factory.bkmr_processor = reactor.callLater( 1, self.factory.select_best_bkmr) return self.factory.RFM(mr_data)