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}
            """)
예제 #2
0
    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')