def handle(self, connection_id, message_content): block_response = network_pb2.GossipBlockResponse() block_response.ParseFromString(message_content) block = block_pb2.Block() block.ParseFromString(block_response.content) open_request = self._responder.get_request(block.header_signature) if open_request is None: return HandlerResult(status=HandlerStatus.PASS) for connection in open_request: LOGGER.debug("Responding to block request: Send %s to %s", block.header_signature, connection) try: self._gossip.send(validator_pb2.Message.GOSSIP_BLOCK_RESPONSE, message_content, connection) except ValueError: LOGGER.debug( "Can't send block response %s to closed " "connection %s", block.header_signature, connection) self._responder.remove_request(block.header_signature) ack = network_pb2.NetworkAcknowledgement() ack.status = ack.OK return HandlerResult(HandlerStatus.RETURN, message_out=ack, message_type=validator_pb2.Message.NETWORK_ACK)
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)
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)
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_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()))
def create_block(): block_header = block_pb2.BlockHeader(block_num=85, state_root_hash="0987654321fedcba", previous_block_id="0000000000000000") block = BlockWrapper( block_pb2.Block(header_signature="abcdef1234567890", header=block_header.SerializeToString())) return block
def _build_block(block_num, block_id, previous_block_id): header = block_pb2.BlockHeader( block_num=block_num, previous_block_id=previous_block_id) return block_pb2.Block( header_signature=block_id, header=header.SerializeToString())
def create_block(block_num=85, previous_block_id="0000000000000000", block_id="abcdef1234567890", batches=None): if batches is None: batches = [] block_header = block_pb2.BlockHeader(block_num=block_num, state_root_hash="0987654321fedcba", previous_block_id=previous_block_id) block = BlockWrapper( block_pb2.Block(header_signature=block_id, header=block_header.SerializeToString(), batches=batches)) return block
def handle(self, connection_id, message_content): block_response = network_pb2.GossipBlockResponse() block_response.ParseFromString(message_content) block = block_pb2.Block() block.ParseFromString(block_response.content) open_request = self._responder.get_request(block.header_signature) if open_request is None: return HandlerResult(status=HandlerStatus.PASS) for connection in open_request: LOGGER.debug("Responding to block request: Send %s to %s", block.header_signature, connection) self._gossip.send(validator_pb2.Message.GOSSIP_BLOCK_RESPONSE, message_content, connection) self._responder.remove_request(block.header_signature) self._responder.purge_requests() return HandlerResult(status=HandlerStatus.PASS)
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")
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")