def handle_multicast_message(self, data): try: common_msg = messages_pb2.CommonMessage() common_msg.ParseFromString(data) join_msg = messages_pb2.Join() join_msg.CopyFrom(common_msg.join) peer = (join_msg.address, join_msg.port) # ignore self if join_msg.address == self.host and join_msg.port == self.port: return with self.message_client.lock: self.message_client.add_peer(peer) ack_msg = self.create_join_message(ack=True) self.message_client.send_message(peer, ack_msg) except socket.error: common_msg = messages_pb2.CommonMessage() common_msg.ParseFromString(data) print(f"""{traceback.print_exc()} My_Host = {self.host} My_Port = {self.port} Data = {data} Parsed = {common_msg} """)
def handle_message(self, request): raw_msg = request.body try: common_msg = messages_pb2.CommonMessage() common_msg.ParseFromString(raw_msg) message_handlers = { messages_pb2.JOIN_MESSAGE: ('Join', 'join', self.add_peer), messages_pb2.TRANSACTION_MESSAGE: ('Transaction', 'transaction', self.handle_transaction), messages_pb2.NODE_QUERY_MESSAGE: ('NodeQuery', 'node_query', self.handle_node_query), messages_pb2.REQUEST_SYNC_GRAPH_MESSAGE: ('RequestSyncGraph', 'request_sync_graph', self.handle_sync_graph), messages_pb2.BATCH_TRANSACTIONS_MESSAGE: ('BatchTransactions', 'batch_transactions', self.handle_batch_transactions), } handler = message_handlers.get(common_msg.message_type) if not handler: raise ValueError( f"There is no message type {common_msg.message_type} or handler not created yet" ) message_classname, attr_name, handler_function = handler sub_msg = getattr(messages_pb2, message_classname)() sub_msg.CopyFrom(getattr(common_msg, attr_name)) return handler_function(request, sub_msg) except Exception: traceback.print_exc() return request.Response(code=500) return request.Response(body=b'')
def request_transaction(self, txn_hash, fulfiller_host, fulfiller_port): request_sync_msg = messages_pb2.RequestSyncGraph() request_sync_msg.address = self.host request_sync_msg.port = self.port request_sync_msg.pubkey = self.keypair.pubkey.to_string().hex() request_sync_msg.target_txn_hash = txn_hash try: msg = MessageClient.create_message( messages_pb2.REQUEST_SYNC_GRAPH_MESSAGE, request_sync_msg) node = (fulfiller_host, fulfiller_port) response = self.send_message(node, msg) common_msg = messages_pb2.CommonMessage() common_msg.ParseFromString(response) sync_graph = messages_pb2.SyncGraph() sync_graph.CopyFrom(common_msg.sync_graph) # only the requested transaction should be returned if len(sync_graph.transactions) != 1: raise ValueError('Expected only 1 transaction') txn = sync_graph.transactions[0] if txn.hash != txn_hash: raise ValueError(f'Wrong transaction hash {txn.hash}') return txn except Exception as e: self.logger.error(e) return None
def get_sub_message(message_type, message): attr_name = ATTR_NAMES.get(message_type) if not attr_name: raise ValueError( f'Invalid message_type {message_type}, or ATTR_NAMES not updated') common_msg = messages_pb2.CommonMessage() common_msg.ParseFromString(message) sub_msg = getattr(common_msg, attr_name) return sub_msg
def create_message(message_type, sub_msg): common_msg = messages_pb2.CommonMessage() common_msg.message_type = message_type attr_name = ATTR_NAMES.get(message_type) if not attr_name: raise ValueError( f'Invalid message_type {message_type}, or ATTR_NAMES not updated') getattr(common_msg, attr_name).CopyFrom(sub_msg) msg = common_msg.SerializeToString() return msg
def _sync_graph(self): time.sleep(params.SYNC_GRAPH_DELAY) self.logger.info( f'Requesting for graph sync...') if self.is_light_client: return request_sync_msg = messages_pb2.RequestSyncGraph() request_sync_msg.address = self.host request_sync_msg.port = self.port request_sync_msg.pubkey = self.keypair.pubkey.to_string().hex() msg = MessageClient.create_message( messages_pb2.REQUEST_SYNC_GRAPH_MESSAGE, request_sync_msg) peers = self.peers.get() responses = [] for peer in peers: response = self.send_message(peer, msg) responses.append(response) largest_txns_size = 0 largest_sync_graph = None for response in responses: common_msg = messages_pb2.CommonMessage() common_msg.ParseFromString(response) sync_graph = messages_pb2.SyncGraph() sync_graph.CopyFrom(common_msg.sync_graph) transactions_size = len(sync_graph.transactions) if transactions_size > largest_txns_size: largest_txns_size = transactions_size largest_sync_graph = sync_graph if largest_sync_graph: self.bootstrap_graph(largest_sync_graph) self.logger.info( f'Synced graph with {largest_txns_size} transactions') else: self.logger.info( 'Aborted sync graph because current node has most updated state')