Beispiel #1
0
    def do_block_responder_handler():
        before_message = network_pb2.GossipBlockRequest(block_id="ABC",
                                                        nonce="1",
                                                        time_to_live=1)

        after_message = network_pb2.GossipBlockRequest(block_id="ABC",
                                                       nonce="1",
                                                       time_to_live=0)

        testResponder.block_request_handler.handle(
            "Connection_1", before_message.SerializeToString())
        # If we cannot respond to the request, broadcast the block request
        # and add to pending request
        testResponder.assert_message_was_broadcasted(
            after_message, validator_pb2.Message.GOSSIP_BLOCK_REQUEST)

        testResponder.assert_request_pending(requested_id="ABC",
                                             connection_id="Connection_1")
        testResponder.assert_message_not_sent(connection_id="Connection_1")

        # Add the block to the completer and resend the Block Request
        block = block_pb2.Block(header_signature="ABC")
        testResponder.completer.add_block(block)

        message = network_pb2.GossipBlockRequest(block_id="ABC",
                                                 nonce="2",
                                                 time_to_live=1)

        testResponder.block_request_handler.handle("Connection_1",
                                                   message.SerializeToString())

        # Check that the a Block Response was sent back to "Connection_1"
        testResponder.assert_message_sent(
            connection_id="Connection_1",
            message_type=validator_pb2.Message.GOSSIP_BLOCK_RESPONSE)
Beispiel #2
0
def test_block_responder_handler():
    """
    Test that the BlockResponderHandler correctly broadcasts a received
    request that the Responder cannot respond to, or sends a
    GossipBlockResponse back to the connection_id the handler received
    the request from.
    """
    # The completer does not have the requested block

    testResponder = TestResponder()

    before_message = network_pb2.GossipBlockRequest(block_id="ABC",
                                                    nonce="1",
                                                    time_to_live=1)

    after_message = network_pb2.GossipBlockRequest(block_id="ABC",
                                                   nonce="1",
                                                   time_to_live=0)

    testResponder.block_request_handler.handle(
        "Connection_1", before_message.SerializeToString())
    # If we cannot respond to the request, broadcast the block request
    # and add to pending request
    # Add the block to the completer and resend the Block Request
    block = block_pb2.Block(header_signature="ABC")
    testResponder.completer.add_block(block)

    message = network_pb2.GossipBlockRequest(block_id="ABC",
                                             nonce="2",
                                             time_to_live=1)

    testResponder.block_request_handler.handle("Connection_1",
                                               message.SerializeToString())
    def test_block_responder_handler_requested(self):
        """
        Test that the BlockResponderHandler correctly broadcasts a received
        request that the Responder cannot respond to, and does not rebroadcast
        the same request.  If we have already recieved the
        request, do nothing.
        """
        before_message = network_pb2.GossipBlockRequest(block_id="ABC",
                                                        nonce="1",
                                                        time_to_live=1)

        after_message = network_pb2.GossipBlockRequest(block_id="ABC",
                                                       nonce="1",
                                                       time_to_live=0)

        self.block_request_handler.handle("Connection_1",
                                          before_message.SerializeToString())
        # If we cannot respond to the request, broadcast the block request
        # and add to pending request
        self.assert_message_was_broadcasted(
            after_message, validator_pb2.Message.GOSSIP_BLOCK_REQUEST)

        self.assert_request_pending(requested_id="ABC",
                                    connection_id="Connection_1")
        self.assert_message_not_sent(connection_id="Connection_1")

        self.gossip.clear()

        # Message should be dropped since the same message has already been
        # handled
        self.block_request_handler.handle("Connection_2",
                                          before_message.SerializeToString())

        self.assert_message_was_not_broadcasted(
            before_message, validator_pb2.Message.GOSSIP_BLOCK_REQUEST)

        self.assert_request_not_pending(requested_id="ABC",
                                        connection_id="Connection_2")

        message = network_pb2.GossipBlockRequest(block_id="ABC",
                                                 nonce="2",
                                                 time_to_live=1)

        self.block_request_handler.handle("Connection_2",
                                          message.SerializeToString())

        self.assert_message_was_not_broadcasted(
            message, validator_pb2.Message.GOSSIP_BLOCK_REQUEST)

        self.assert_request_pending(requested_id="ABC",
                                    connection_id="Connection_2")
        self.assert_message_not_sent(connection_id="Connection_2")
Beispiel #4
0
    def handle(self, connection_id, message_content):
        block_request_message = network_pb2.GossipBlockRequest()
        block_request_message.ParseFromString(message_content)
        block_id = block_request_message.block_id
        node_id = block_request_message.node_id
        block = self._responder.check_for_block(block_id)
        if block is None:
            # No block found, broadcast original message to other peers
            # and add to pending requests
            if block_id == "HEAD":
                LOGGER.debug("No chain head available. Cannot respond to block"
                             " requests.")
            else:
                self._responder.add_request(block_id, connection_id)
                self._gossip.broadcast(
                    block_request_message,
                    validator_pb2.Message.GOSSIP_BLOCK_REQUEST,
                    exclude=[connection_id])
        else:
            LOGGER.debug("Responding to block requests: %s",
                         block.get_block().header_signature)

            block_response = network_pb2.GossipBlockResponse(
                content=block.get_block().SerializeToString(), node_id=node_id)

            self._gossip.send(validator_pb2.Message.GOSSIP_BLOCK_RESPONSE,
                              block_response.SerializeToString(),
                              connection_id)

        return HandlerResult(status=HandlerStatus.PASS)
Beispiel #5
0
    def test_block_responder_handler(self):
        """
        Test that the BlockResponderHandler correctly broadcasts a received
        request that the Responder cannot respond to, or sends a
        GossipBlockResponse back to the connection_id the handler received
        the request from.
        """
        # The completer does not have the requested block
        message = network_pb2.GossipBlockRequest(block_id="ABC", node_id=b"1")
        self.block_request_handler.handle("Connection_1",
                                          message.SerializeToString())
        # If we cannot respond to the request, broadcast the block request
        # and add to pending request
        self.assert_message_was_broadcasted(
            message, validator_pb2.Message.GOSSIP_BLOCK_REQUEST)

        self.assert_request_pending(requested_id="ABC",
                                    connection_id="Connection_1")
        self.assert_message_not_sent(connection_id="Connection_1")

        # Add the block to the completer and resend the Block Request
        block = block_pb2.Block(header_signature="ABC")
        self.completer.add_block(block)
        self.block_request_handler.handle("Connection_1",
                                          message.SerializeToString())

        # Check that the a Block Response was sent back to "Connection_1"
        self.assert_message_sent(
            connection_id="Connection_1",
            message_type=validator_pb2.Message.GOSSIP_BLOCK_RESPONSE)
Beispiel #6
0
def test_responder_block_response_handler():
    """
    Test that the ResponderBlockResponseHandler, after receiving a Block
    Response, checks to see if the responder has any pending request for
    that response and forwards the response on to the connection_id that
    had requested it.
    """
    # The Responder does not have any pending requests for block "ABC"
    testResponder = TestResponder()

    block = block_pb2.Block(header_signature="ABC")
    response_message = network_pb2.GossipBlockResponse(
        content=block.SerializeToString())

    testResponder.block_response_handler.handle(
        "Connection_1", (block, response_message.SerializeToString()))

    # ResponderBlockResponseHandler should not send any messages.
    # Handle a request message for block "ABC". This adds it to the pending
    # request queue.
    request_message = \
        network_pb2.GossipBlockRequest(block_id="ABC", time_to_live=1)

    testResponder.block_request_handler.handle(
        "Connection_2", request_message.SerializeToString())

    # Handle the the BlockResponse Message. Since Connection_2 had
    # requested the block but it could not be fulfilled at that time of the
    # request the received BlockResponse is forwarded to Connection_2
    testResponder.block_response_handler.handle(
        "Connection_1", (block, response_message.SerializeToString()))
Beispiel #7
0
    def do_block_responder_handler_requested():
        before_message = network_pb2.GossipBlockRequest(block_id="ABC",
                                                        nonce="1",
                                                        time_to_live=1)

        after_message = network_pb2.GossipBlockRequest(block_id="ABC",
                                                       nonce="1",
                                                       time_to_live=0)

        testResponder.block_request_handler.handle(
            "Connection_1", before_message.SerializeToString())
        # If we cannot respond to the request, broadcast the block request
        # and add to pending request
        testResponder.assert_message_was_broadcasted(
            after_message, validator_pb2.Message.GOSSIP_BLOCK_REQUEST)

        testResponder.assert_request_pending(requested_id="ABC",
                                             connection_id="Connection_1")
        testResponder.assert_message_not_sent(connection_id="Connection_1")

        testResponder.gossip.clear()

        # Message should be dropped since the same message has already been
        # handled
        testResponder.block_request_handler.handle(
            "Connection_2", before_message.SerializeToString())

        testResponder.assert_message_was_not_broadcasted(
            before_message, validator_pb2.Message.GOSSIP_BLOCK_REQUEST)

        testResponder.assert_request_not_pending(requested_id="ABC",
                                                 connection_id="Connection_2")

        message = network_pb2.GossipBlockRequest(block_id="ABC",
                                                 nonce="2",
                                                 time_to_live=1)

        testResponder.block_request_handler.handle("Connection_2",
                                                   message.SerializeToString())

        testResponder.assert_message_was_not_broadcasted(
            message, validator_pb2.Message.GOSSIP_BLOCK_REQUEST)

        testResponder.assert_request_pending(requested_id="ABC",
                                             connection_id="Connection_2")
        testResponder.assert_message_not_sent(connection_id="Connection_2")
Beispiel #8
0
    def handle(self, connection_id, message_content):
        block_request_message = network_pb2.GossipBlockRequest()
        block_request_message.ParseFromString(message_content)
        if block_request_message.nonce in self._seen_requests:
            LOGGER.debug("Received repeat GossipBlockRequest from %s",
                         connection_id)
            ack = network_pb2.NetworkAcknowledgement()
            ack.status = ack.OK

            return HandlerResult(
                HandlerStatus.RETURN,
                message_out=ack,
                message_type=validator_pb2.Message.NETWORK_ACK)

        self._seen_requests[block_request_message.nonce] = \
            block_request_message.block_id

        block_id = block_request_message.block_id
        node_id = block_request_message.node_id
        block = self._responder.check_for_block(block_id)
        if block is None:
            # No block found, broadcast original message to other peers
            # and add to pending requests
            if block_id == "HEAD":
                LOGGER.debug("No chain head available. Cannot respond to block"
                             " requests.")
            else:
                if not self._responder.already_requested(block_id):
                    self._gossip.broadcast(
                        block_request_message,
                        validator_pb2.Message.GOSSIP_BLOCK_REQUEST,
                        exclude=[connection_id])
                else:
                    LOGGER.debug("Block %s has already been requested",
                                 block_id)

                self._responder.add_request(block_id, connection_id)
        else:
            LOGGER.debug("Responding to block requests: %s",
                         block.get_block().header_signature)

            block_response = network_pb2.GossipBlockResponse(
                content=block.get_block().SerializeToString(), node_id=node_id)

            self._gossip.send(validator_pb2.Message.GOSSIP_BLOCK_RESPONSE,
                              block_response.SerializeToString(),
                              connection_id)

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

        return HandlerResult(HandlerStatus.RETURN,
                             message_out=ack,
                             message_type=validator_pb2.Message.NETWORK_ACK)
Beispiel #9
0
    def handle(self, connection_id, message_content):
        block_request_message = network_pb2.GossipBlockRequest()
        block_request_message.ParseFromString(message_content)
        if block_request_message.nonce in self._seen_requests:
            LOGGER.debug("Received repeat GossipBlockRequest from %s",
                         connection_id)

            return HandlerResult(HandlerStatus.DROP)

        block_id = block_request_message.block_id
        block = self._responder.check_for_block(block_id)
        if block is None:
            # No block found, broadcast original message to other peers
            # and add to pending requests
            if block_id == "HEAD":
                if not self._log_guard.chain_head_not_yet_set:
                    LOGGER.debug("No chain head available; cannot respond to "
                                 "block requests")
                    self._log_guard.chain_head_not_yet_set = True
            else:
                if not self._responder.already_requested(block_id):
                    if block_request_message.time_to_live > 0:
                        time_to_live = block_request_message.time_to_live
                        block_request_message.time_to_live = time_to_live - 1
                        self._gossip.broadcast(
                            block_request_message,
                            validator_pb2.Message.GOSSIP_BLOCK_REQUEST,
                            exclude=[connection_id])

                        self._seen_requests[block_request_message.nonce] = \
                            block_request_message.block_id

                        self._responder.add_request(block_id, connection_id)
                else:
                    LOGGER.debug("Block %s has already been requested",
                                 block_id)

                    self._responder.add_request(block_id, connection_id)
        else:
            LOGGER.debug("Responding to block requests: %s",
                         block.header_signature)

            block_response = network_pb2.GossipBlockResponse(
                content=block.SerializeToString())

            self._gossip.send(validator_pb2.Message.GOSSIP_BLOCK_RESPONSE,
                              block_response.SerializeToString(),
                              connection_id)

        return HandlerResult(HandlerStatus.PASS)
Beispiel #10
0
def test_block_responder_handler_requested():
    """
    Test that the BlockResponderHandler correctly broadcasts a received
    request that the Responder cannot respond to, and does not rebroadcast
    the same request.  If we have already recieved the
    request, do nothing.
    """

    testResponder = TestResponder()

    before_message = network_pb2.GossipBlockRequest(block_id="ABC",
                                                    nonce="1",
                                                    time_to_live=1)

    after_message = network_pb2.GossipBlockRequest(block_id="ABC",
                                                   nonce="1",
                                                   time_to_live=0)

    testResponder.block_request_handler.handle(
        "Connection_1", before_message.SerializeToString())
    # If we cannot respond to the request, broadcast the block request
    # and add to pending request

    testResponder.gossip.clear()

    # Message should be dropped since the same message has already been
    # handled
    testResponder.block_request_handler.handle(
        "Connection_2", before_message.SerializeToString())

    message = network_pb2.GossipBlockRequest(block_id="ABC",
                                             nonce="2",
                                             time_to_live=1)

    testResponder.block_request_handler.handle("Connection_2",
                                               message.SerializeToString())
Beispiel #11
0
    def handle(self, connection_id, message_content):
        gossip_message = network_pb2.GossipBlockRequest()
        gossip_message.ParseFromString(message_content)
        block_id = gossip_message.block_id
        block = self._responder.check_for_block(block_id)
        if block is None:
            # No block found, broadcast orignal message to other peers
            self._gossip.broadcast(gossip_message,
                                   validator_pb2.Message.GOSSIP_BLOCK_REQUEST)
        else:
            # Found block, Currently we create a new gossip message, in the
            # the future a direct message to the node that requested the block
            # will be used.
            LOGGER.debug("Responding to block requests: %s",
                         block.get_block().header_signature)
            self._gossip.broadcast_block(block.get_block())

        return HandlerResult(status=HandlerStatus.PASS)
Beispiel #12
0
    def test_responder_block_response_handler(self):
        """
        Test that the ResponderBlockResponseHandler, after receiving a Block
        Response, checks to see if the responder has any pending request for
        that response and forwards the response on to the connection_id that
        had requested it.
        """
        # The Responder does not have any pending requests for block "ABC"
        block = block_pb2.Block(header_signature="ABC")
        response_message = network_pb2.GossipBlockResponse(
            content=block.SerializeToString())

        self.block_response_handler.handle(
            "Connection_1", response_message.SerializeToString())

        # ResponderBlockResponseHandler should not send any messages.
        self.assert_message_not_sent("Connection_1")
        self.assert_request_not_pending(requested_id="ABC")

        # Handle a request message for block "ABC". This adds it to the pending
        # request queue.
        request_message = \
            network_pb2.GossipBlockRequest(block_id="ABC")

        self.block_request_handler.handle(
            "Connection_2", request_message.SerializeToString())

        self.assert_request_pending(
            requested_id="ABC", connection_id="Connection_2")

        # Handle the the BlockResponse Message. Since Connection_2 had
        # requested the block but it could not be fulfilled at that time of the
        # request the received BlockResponse is forwarded to Connection_2
        self.block_response_handler.handle(
            "Connection_1", response_message.SerializeToString())

        self.assert_message_sent(
            connection_id="Connection_2",
            message_type=validator_pb2.Message.GOSSIP_BLOCK_RESPONSE
            )
        # The request for block "ABC" from "Connection_2" is no longer pending
        # it should be removed from the pending request cache.
        self.assert_request_not_pending(requested_id="ABC")
Beispiel #13
0
    def do_responder_block_response_handler():

        block = block_pb2.Block(header_signature="ABC")
        response_message = network_pb2.GossipBlockResponse(
            content=block.SerializeToString())

        testResponder.block_response_handler.handle(
            "Connection_1", (block, response_message.SerializeToString()))

        # ResponderBlockResponseHandler should not send any messages.
        testResponder.assert_message_not_sent("Connection_1")
        testResponder.assert_request_not_pending(requested_id="ABC")

        # Handle a request message for block "ABC". This adds it to the pending
        # request queue.
        request_message = \
            network_pb2.GossipBlockRequest(block_id="ABC", time_to_live=1)

        testResponder.block_request_handler.handle(
            "Connection_2", request_message.SerializeToString())

        testResponder.assert_request_pending(requested_id="ABC",
                                             connection_id="Connection_2")

        # Handle the the BlockResponse Message. Since Connection_2 had
        # requested the block but it could not be fulfilled at that time of the
        # request the received BlockResponse is forwarded to Connection_2
        testResponder.block_response_handler.handle(
            "Connection_1", (block, response_message.SerializeToString()))

        testResponder.assert_message_sent(
            connection_id="Connection_2",
            message_type=validator_pb2.Message.GOSSIP_BLOCK_RESPONSE)
        # The request for block "ABC" from "Connection_2" is no longer pending
        # it should be removed from the pending request cache.
        testResponder.assert_request_not_pending(requested_id="ABC")
Beispiel #14
0
    def handle(self, connection_id, message_content):
        block_request_message = network_pb2.GossipBlockRequest()
        block_request_message.ParseFromString(message_content)
        if block_request_message.nonce in self._seen_requests:
            LOGGER.debug("Received repeat GossipBlockRequest from %s",
                         connection_id)

            return HandlerResult(HandlerStatus.DROP)
        """
        block_id format - HEAD/ID/N<NUM>.ID
        """
        block_id = block_request_message.block_id
        block_num = None
        if block_id[0] == 'N':
            # contain block number
            parts = block_id.split('.')
            block_id = parts[1]
            block_num = parts[0][1:]

        block = self._responder.check_for_block(block_id)
        LOGGER.debug("BlockResponderHandler:ID=%s NUM=%s nonce=%s BLOCK=%s.",
                     block_id if block_id == "HEAD" else block_id[:8],
                     block_num, block_request_message.nonce, block)
        if block is None:
            # No block found, broadcast original message to other peers
            # and add to pending requests
            if block_id == "HEAD":
                LOGGER.debug(
                    "No chain head available. Cannot respond to block requests."
                )
            else:
                if not self._responder.already_requested(block_id):
                    if block_request_message.time_to_live > 0:
                        time_to_live = block_request_message.time_to_live
                        block_request_message.time_to_live = time_to_live - 1
                        self._gossip.broadcast(
                            block_request_message,
                            validator_pb2.Message.GOSSIP_BLOCK_REQUEST,
                            exclude=[connection_id])

                        self._seen_requests[
                            block_request_message.
                            nonce] = block_request_message.block_id

                        self._responder.add_request(block_id, connection_id)
                else:
                    LOGGER.debug("Block %s has already been requested",
                                 block_id[:8])

                    self._responder.add_request(block_id, connection_id)
        else:
            """
            check if there is a GAP between block_num and block.block_num send block block_num-1 instead block
            peer as block
            """
            if block_id != "HEAD":
                blocks = []
                nest = False
                gap = Federation.gap_feder_num(
                    block_num, block.block_num) if block_num else 0
                LOGGER.debug("Responding to block requests: BLOCK=%s GAP=%s",
                             block.get_block().header_signature[:8], gap)
                if gap > 1:
                    # get block by number
                    num = int(Federation.dec_feder_num(block_num))
                    # save request
                    self._responder.add_request(block_id, connection_id)
                    try:
                        block = self._responder.get_block_by_num(num)
                        blocks.append(block)
                        LOGGER.debug("Responding BLOCK=%s", block)
                    except KeyError:
                        LOGGER.debug("THERE IS NO Responding BLOCK=%s", num)

                else:
                    # check may be prev block already was asked
                    blocks.append(block)
                while True:
                    prev_num = int(Federation.dec_feder_num(block.block_num))
                    try:
                        block = self._responder.get_block_by_num(prev_num)
                    except KeyError:
                        LOGGER.debug("THERE IS NO Responding BLOCK=%s",
                                     prev_num)
                        break
                    prev_block_id = block.get_block().header_signature
                    if self._responder.already_requested(prev_block_id):
                        self._responder.remove_request(prev_block_id)
                        blocks.append(block)
                    else:
                        break
            else:
                blocks = block  # list of heads
                nest = True

            for block in blocks:
                LOGGER.debug("Responding nest=%s SEND BLOCK=%s", nest, block)
                block_response = network_pb2.GossipBlockResponse(
                    content=block.get_block().SerializeToString(), nest=nest)
                self._gossip.send(validator_pb2.Message.GOSSIP_BLOCK_RESPONSE,
                                  block_response.SerializeToString(),
                                  connection_id)

        return HandlerResult(HandlerStatus.PASS)