Exemplo n.º 1
0
    def handle(self, connection_id, message_content):
        gossip_message = GossipMessage()
        gossip_message.ParseFromString(message_content)
        if gossip_message.content_type == "BLOCK":
            block = Block()
            block.ParseFromString(gossip_message.content)
            status = validate_block(block)
            if status is True:
                LOGGER.debug("block passes signature verification %s",
                             block.header_signature)
                return HandlerResult(status=HandlerStatus.PASS)

            LOGGER.debug("block signature is invalid: %s",
                         block.header_signature)
            return HandlerResult(status=HandlerStatus.DROP)
        elif gossip_message.content_type == "BATCH":
            batch = Batch()
            batch.ParseFromString(gossip_message.content)
            status = validate_batch(batch)
            if status is True:
                LOGGER.debug("batch passes signature verification %s",
                             batch.header_signature)
                return HandlerResult(status=HandlerStatus.PASS)
            LOGGER.debug("batch signature is invalid: %s",
                         batch.header_signature)
            return HandlerResult(status=HandlerStatus.DROP)
    def handle(self, connection_id, message_content):
        message = GossipMessage()
        message.ParseFromString(message_content)
        if message.content_type == "BLOCK":
            public_key = \
                self._network.connection_id_to_public_key(connection_id)
            block = Block()
            block.ParseFromString(message.content)
            header = BlockHeader()
            header.ParseFromString(block.header)
            if header.signer_public_key == public_key:
                permitted = \
                    self._permission_verifier.check_network_consensus_role(
                        public_key)
                if not permitted:
                    LOGGER.debug(
                        "Public key is not permitted to publish block, "
                        "remove connection: %s", connection_id)
                    self._gossip.unregister_peer(connection_id)
                    violation = AuthorizationViolation(
                        violation=RoleType.Value("NETWORK"))
                    return HandlerResult(HandlerStatus.RETURN_AND_CLOSE,
                                         message_out=violation,
                                         message_type=validator_pb2.Message.
                                         AUTHORIZATION_VIOLATION)

        # if allowed pass message
        return HandlerResult(HandlerStatus.PASS)
    def handle(self, connection_id, message_content):
        gossip_message = GossipMessage()
        gossip_message.ParseFromString(message_content)
        if gossip_message.content_type == gossip_message.BLOCK:
            block = Block()
            block.ParseFromString(gossip_message.content)
            has_block = False
            if self._completer.get_block(block.header_signature) is not None:
                has_block = True

            if not has_block and self._has_block(block.header_signature):
                has_block = True

            if has_block:
                LOGGER.debug("Drop duplicate block: %s",
                             block.header_signature)
                return HandlerResult(HandlerStatus.DROP)

        if gossip_message.content_type == gossip_message.BATCH:
            batch = Batch()
            batch.ParseFromString(gossip_message.content)
            has_batch = False
            if self._completer.get_batch(batch.header_signature) is not None:
                has_batch = True

            if not has_batch and self._has_batch(batch.header_signature):
                has_batch = True

            if has_batch:
                LOGGER.debug("Drop duplicate batch: %s",
                             batch.header_signature)
                return HandlerResult(HandlerStatus.DROP)

        return HandlerResult(HandlerStatus.PASS)
    def handle(self, connection_id, message_content):
        exclude = [connection_id]
        gossip_message = GossipMessage()
        gossip_message.ParseFromString(message_content)
        if gossip_message.time_to_live == 0:
            # Do not forward message if it has reached its time to live limit
            return HandlerResult(status=HandlerStatus.PASS)

        else:
            # decrement time_to_live
            time_to_live = gossip_message.time_to_live
            gossip_message.time_to_live = time_to_live - 1

        if gossip_message.content_type == GossipMessage.BATCH:
            batch = Batch()
            batch.ParseFromString(gossip_message.content)
            # If we already have this batch, don't forward it
            if not self._completer.get_batch(batch.header_signature):
                self._gossip.broadcast_batch(batch, exclude)
        elif gossip_message.content_type == GossipMessage.BLOCK:
            block = Block()
            block.ParseFromString(gossip_message.content)
            # If we already have this block, don't forward it
            if not self._completer.get_block(block.header_signature):
                self._gossip.broadcast_block(block, exclude)
        else:
            LOGGER.info("received %s, not BATCH or BLOCK",
                        gossip_message.content_type)
        return HandlerResult(status=HandlerStatus.PASS)
Exemplo n.º 5
0
    def test_signature_thread(self):
        try:
            self.verifier.start()
            blocks = self._create_blocks(1, 1)
            message = GossipMessage(content_type="Block",
                                    content=blocks[0].SerializeToString())
            content = message.SerializeToString()
            msg = validator_pb2.Message(
                message_type=validator_pb2.Message.GOSSIP_MESSAGE,
                correlation_id=self._generate_id(),
                content=content)

            with self._in_condition:
                self._in.put_nowait(msg)
                self._in_condition.notify_all()

            to = TimeOut(2)
            while self._out.qsize() == 0:
                if to.is_timed_out():
                    break

            self.assertEqual(self._out.qsize(), 1)

        finally:
            with self._in_condition:
                self.verifier.stop()
                self._in_condition.notify_all()
Exemplo n.º 6
0
    def handle(self, identity, message_content):

        ack = NetworkAcknowledgement()
        ack.status = ack.OK
        gossip_message = GossipMessage()
        gossip_message.ParseFromString(message_content)

        return HandlerResult(HandlerStatus.RETURN_AND_PASS,
                             message_out=ack,
                             message_type=validator_pb2.Message.GOSSIP_ACK)
Exemplo n.º 7
0
 def test_no_block(self):
     """
     Test that if the block does not exist yet in the completer or the
     chain controller, the gossip message is passed.
     """
     block = Block(header_signature="Block1")
     message = GossipMessage(content_type=GossipMessage.BLOCK,
                             content=block.SerializeToString())
     handler_status = self.handler.handle("connection_id",
                                          message.SerializeToString())
     self.assertEqual(handler_status.status, HandlerStatus.PASS)
Exemplo n.º 8
0
 def test_publisher_has_block(self):
     """
     Test that if the block does not exist yet in the completer or the
     chain controller, the gossip message is passed.
     """
     batch = Batch(header_signature="Batch1")
     self.publisher.add_batch("Batch1")
     message = GossipMessage(content_type=GossipMessage.BATCH,
                             content=batch.SerializeToString())
     handler_status = self.handler.handle(
         "connection_id", message.SerializeToString())
     self.assertEqual(handler_status.status, HandlerStatus.DROP)
Exemplo n.º 9
0
 def handle(self, identity, message_content):
     gossip_message = GossipMessage()
     gossip_message.ParseFromString(message_content)
     if gossip_message.content_type == "BATCH":
         batch = Batch()
         batch.ParseFromString(gossip_message.content)
         self._gossip.broadcast_batch(batch)
     elif gossip_message.content_type == "BLOCK":
         block = Block()
         block.ParseFromString(gossip_message.content)
         self._gossip.broadcast_block(block)
     else:
         LOGGER.info("received %s, not BATCH or BLOCK",
                     gossip_message.content_type)
     return HandlerResult(status=HandlerStatus.PASS)
Exemplo n.º 10
0
    def handle(self, connection_id, message_content):
        gossip_message = GossipMessage()
        gossip_message.ParseFromString(message_content)

        if gossip_message.content_type == GossipMessage.BLOCK:
            block = Block()
            block.ParseFromString(gossip_message.content)

            if block.header_signature in self._seen_cache:
                LOGGER.debug("Drop already validated block: %s cache=%s",
                             block.header_signature[:8], len(self._seen_cache)
                             )  #[sig[:8] for sig in self._seen_cache])
                return HandlerResult(status=HandlerStatus.DROP)

            if not is_valid_block(block):
                LOGGER.debug("block signature is invalid: %s",
                             block.header_signature[:8])
                return HandlerResult(status=HandlerStatus.DROP)

            self._seen_cache[block.header_signature] = None
            return HandlerResult(status=HandlerStatus.PASS)

        elif gossip_message.content_type == GossipMessage.BATCH:
            batch = Batch()
            batch.ParseFromString(gossip_message.content)
            if batch.header_signature in self._seen_cache:
                LOGGER.debug("Drop already validated batch: %s",
                             batch.header_signature[:8])
                return HandlerResult(status=HandlerStatus.DROP)

            if not is_valid_batch(batch):
                LOGGER.debug("batch signature is invalid: %s",
                             batch.header_signature[:8])
                return HandlerResult(status=HandlerStatus.DROP)

            self._seen_cache[batch.header_signature] = None
            return HandlerResult(status=HandlerStatus.PASS)
        elif gossip_message.content_type == GossipMessage.BATCHES:
            # check batches signature
            LOGGER.debug("Check BATCHES signature!!!")
            return HandlerResult(status=HandlerStatus.PASS)
        elif gossip_message.content_type == GossipMessage.ENDPOINTS:
            # check endpoints
            LOGGER.debug("Check ENDPOINTS signature!!!")
            return HandlerResult(status=HandlerStatus.PASS)

        # should drop the message if it does not have a valid content_type
        return HandlerResult(status=HandlerStatus.DROP)
Exemplo n.º 11
0
 def broadcast_consensus_message(self, message_envelope):
     self.broadcast(
         GossipMessage(
             content_type=GossipMessage.CONSENSUS,
             content=message_envelope.SerializeToString(),
             time_to_live=self.get_time_to_live()),
         validator_pb2.Message.GOSSIP_MESSAGE)
Exemplo n.º 12
0
def gossip_message_preprocessor(message_content_bytes):
    gossip_message = GossipMessage()
    gossip_message.ParseFromString(message_content_bytes)

    tag = gossip_message.content_type

    if tag == GossipMessage.BLOCK:
        obj = Block()
        obj.ParseFromString(gossip_message.content)
    elif tag == GossipMessage.BATCH:
        obj = Batch()
        obj.ParseFromString(gossip_message.content)

    content = obj, tag, gossip_message.time_to_live

    return PreprocessorResult(content=content)
Exemplo n.º 13
0
    def broadcast_batch(self, batch, exclude=None):
        gossip_message = GossipMessage(
            content_type="BATCH",
            content=batch.SerializeToString())

        self.broadcast(
            gossip_message, validator_pb2.Message.GOSSIP_MESSAGE, exclude)
Exemplo n.º 14
0
    def broadcast_block(self, block, exclude=None):
        gossip_message = GossipMessage(
            content_type="BLOCK",
            content=block.SerializeToString())

        self.broadcast(
            gossip_message, validator_pb2.Message.GOSSIP_MESSAGE, exclude)
Exemplo n.º 15
0
    def broadcast_batch(self, batch, exclude=None):
        time_to_live = self.get_time_to_live()
        gossip_message = GossipMessage(content_type=GossipMessage.BATCH,
                                       content=batch.SerializeToString(),
                                       time_to_live=time_to_live)

        self.broadcast(gossip_message, validator_pb2.Message.GOSSIP_MESSAGE,
                       exclude)
Exemplo n.º 16
0
    def handle(self, message, peer):
        LOGGER.debug("GossipMessageHandler message: %s", message.sender)
        request = GossipMessage()
        request.ParseFromString(message.content)

        LOGGER.debug("Got gossip message %s "
                     "from %s. sending ack", message.content, message.sender)

        self._ingest_message(request)

        ack = NetworkAcknowledgement()
        ack.status = ack.OK

        peer.send(
            validator_pb2.Message(sender=message.sender,
                                  message_type='gossip/ack',
                                  correlation_id=message.correlation_id,
                                  content=ack.SerializeToString()))
Exemplo n.º 17
0
    def broadcast_block(self, block, exclude=None, time_to_live=None):
        if time_to_live is None:
            time_to_live = self.get_time_to_live()
        gossip_message = GossipMessage(content_type=GossipMessage.BLOCK,
                                       content=block.SerializeToString(),
                                       time_to_live=time_to_live)

        self.broadcast(gossip_message, validator_pb2.Message.GOSSIP_MESSAGE,
                       exclude)
Exemplo n.º 18
0
    def handle(self, message, peer):
        LOGGER.debug("GossipMessageHandler message: {}".format(message))
        request = GossipMessage()
        request.ParseFromString(message.content)

        LOGGER.debug("Got gossip message {} "
                     "from {}. sending ack".format(message.content,
                                                   message.sender))

        self._service._put_on_inbound(request)

        ack = NetworkAcknowledgement()
        ack.status = ack.OK

        peer.send(validator_pb2.Message(
            sender=message.sender,
            message_type='gossip/ack',
            correlation_id=message.correlation_id,
            content=ack.SerializeToString()))
Exemplo n.º 19
0
    def send_consensus_message(self, peer_id, message_envelope):
        connection_id = self._network.public_key_to_connection_id(peer_id)

        self.send(
            validator_pb2.Message.GOSSIP_MESSAGE,
            GossipMessage(
                content_type=GossipMessage.CONSENSUS,
                content=message_envelope.SerializeToString(),
                time_to_live=self.get_time_to_live()).SerializeToString(),
            connection_id)
Exemplo n.º 20
0
    def handle(self, connection_id, message_content):
        gossip_message = GossipMessage()
        gossip_message.ParseFromString(message_content)

        if gossip_message.content_type == GossipMessage.BLOCK:
            block = Block()
            block.ParseFromString(gossip_message.content)

            if block.header_signature in self._seen_cache:
                LOGGER.debug("Drop already validated block: %s",
                             block.header_signature)
                return HandlerResult(status=HandlerStatus.DROP)

            if not is_valid_block(block):
                LOGGER.debug("block signature is invalid: %s",
                             block.header_signature)
                return HandlerResult(status=HandlerStatus.DROP)

            LOGGER.debug("block passes signature verification %s",
                         block.header_signature)
            self._seen_cache[block.header_signature] = None
            return HandlerResult(status=HandlerStatus.PASS)

        elif gossip_message.content_type == GossipMessage.BATCH:
            batch = Batch()
            batch.ParseFromString(gossip_message.content)
            if batch.header_signature in self._seen_cache:
                LOGGER.debug("Drop already validated batch: %s",
                             batch.header_signature)
                return HandlerResult(status=HandlerStatus.DROP)

            if not is_valid_batch(batch):
                LOGGER.debug("batch signature is invalid: %s",
                             batch.header_signature)
                return HandlerResult(status=HandlerStatus.DROP)

            LOGGER.debug("batch passes signature verification %s",
                         batch.header_signature)
            self._seen_cache[batch.header_signature] = None
            return HandlerResult(status=HandlerStatus.PASS)

        # should drop the message if it does not have a valid content_type
        return HandlerResult(status=HandlerStatus.DROP)
Exemplo n.º 21
0
 def handle(self, connection_id, message_content):
     exclude = [connection_id]
     gossip_message = GossipMessage()
     gossip_message.ParseFromString(message_content)
     if gossip_message.content_type == "BATCH":
         batch = Batch()
         batch.ParseFromString(gossip_message.content)
         # If we already have this batch, don't forward it
         if not self._completer.get_batch(batch.header_signature):
             self._gossip.broadcast_batch(batch, exclude)
     elif gossip_message.content_type == "BLOCK":
         block = Block()
         block.ParseFromString(gossip_message.content)
         # If we already have this block, don't forward it
         if not self._completer.get_block(block.header_signature):
             self._gossip.broadcast_block(block, exclude)
     else:
         LOGGER.info("received %s, not BATCH or BLOCK",
                     gossip_message.content_type)
     return HandlerResult(status=HandlerStatus.PASS)
Exemplo n.º 22
0
    def __init__(self, identity, endpoint, peer_list, dispatcher):
        LOGGER.debug("Initializing Network service")
        self._identity = identity
        self._dispatcher = dispatcher
        self._handlers = {}
        self._peered_with_us = {}
        self.inbound_queue = queue.Queue()
        self._futures = future.FutureCollection()
        self._send_receive_thread = _ServerSendReceiveThread(endpoint,
                                                             self._handlers,
                                                             self._futures)

        self._send_receive_thread.daemon = True
        self.add_handler('default', DefaultHandler())
        self.add_handler('gossip/register',
                         PeerRegisterHandler(self))
        self.add_handler('gossip/unregister',
                         PeerUnregisterHandler(self))
        self.add_handler('gossip/msg',
                         GossipMessageHandler(self))
        self.start()

        if peer_list is not None:
            for peer in peer_list:
                self._send_receive_thread.add_connection(self._identity, peer)

            LOGGER.info("Sleeping 5 seconds and then broadcasting messages "
                        "to connected peers")
            time.sleep(5)

            content = GossipMessage(content=bytes(
                str("This is a gossip payload"), 'UTF-8')).SerializeToString()

            for _ in range(1000):
                message = validator_pb2.Message(
                    message_type=b'gossip/msg',
                    correlation_id=_generate_id(),
                    content=content)

                self.broadcast_message(message)

                # If we transmit as fast as possible, we populate the
                # buffers and get faster throughput but worse avg. message
                # latency. If we sleep here or otherwise throttle input,
                # the overall duration is longer, but the per message
                # latency is low. The process is CPU bound on Vagrant VM
                # core at ~0.001-0.01 duration sleeps.
                time.sleep(0.01)
Exemplo n.º 23
0
    def send_message(self, data):
        if isinstance(data, str):
            msg = GossipMessage(content_type="BlockRequest",
                                content=data.encode("utf-8"))
        elif isinstance(data, block_pb2.Block):
            msg = GossipMessage(content_type="Block",
                                content=data.SerializeToString())
        elif isinstance(data, batch_pb2.Batch):
            msg = GossipMessage(content_type="Batch",
                                content=data.SerializeToString())

        content = msg.SerializeToString()
        message = validator_pb2.Message(
            message_type=validator_pb2.Message.GOSSIP_MESSAGE,
            correlation_id=_generate_id(),
            content=content)

        self._put_on_inbound(message)
    def test_signature_thread(self):
        try:
            self.verifier.start()
            blocks = self._create_blocks(1, 1)
            msg = GossipMessage(content_type="Block",
                                content=blocks[0].SerializeToString())
            with self._in_condition:
                self._in.put_nowait(msg)
                self._in_condition.notify_all()

            to = TimeOut(2)
            while self._out.qsize() == 0:
                if to.is_timed_out():
                    break

            self.assertEqual(self._out.qsize(), 1)

        finally:
            with self._in_condition:
                self.verifier.stop()
                self._in_condition.notify_all()
Exemplo n.º 25
0
    def run(self):
        while True:
            if self._exit:
                return
            try:
                message = self.incoming_msg_queue.get(block=False)
                request = GossipMessage()
                request.ParseFromString(message.content)
                if request.content_type == "Block":
                    try:
                        block = Block()
                        block.ParseFromString(request.content)
                        status = self.validate_block(block)
                        if status:
                            LOGGER.debug("Pass block to dispatch %s",
                                         block.header_signature)
                            self.dispatcher_msg_queue.put_nowait(request)
                            self.broadcast(message)
                            with self.dispatcher_condition:
                                self.dispatcher_condition.notify_all()

                        else:
                            LOGGER.debug("Block signature is invalid: %s",
                                         block.header_signature)
                    except DecodeError as e:
                        # what to do with a bad msg
                        LOGGER.warning(
                            "Problem decoding GossipMessage for "
                            "Block, %s", e)

                elif request.content_type == "Batch":
                    try:
                        batch = Batch()
                        batch.ParseFromString(request.content)
                        status = self.validate_batch(batch)
                        if status:
                            self.dispatcher_msg_queue.put_nowait(request)
                            self.broadcast(message)
                            with self.dispatcher_condition:
                                self.dispatcher_condition.notify_all()

                        else:
                            LOGGER.debug("Batch signature is invalid: %s",
                                         batch.header_signature)
                    except DecodeError as e:
                        LOGGER.warning(
                            "Problem decoding GossipMessage for "
                            "Batch, %s", e)

                elif request.content_type == "BlockRequest":
                    self.dispatcher_msg_queue.put_notwait(request)
                    with self.dispatcher_condition:
                        self.dispatcher_condition.notify_all()

                elif request.content_type == "Test":
                    LOGGER.debug("Verifier Handle Test")
                    self.dispatcher_msg_queue.put_nowait(request)
                    with self.dispatcher_condition:
                        self.dispatcher_condition.notify_all()

            except queue.Empty:
                with self.in_condition:
                    self.in_condition.wait()