def do_responder_batch_response_txn_handler(): transaction = transaction_pb2.Transaction(header_signature="123") batch = batch_pb2.Batch(header_signature="abc", transactions=[transaction]) response_message = network_pb2.GossipBatchResponse( content=batch.SerializeToString()) request_message = \ network_pb2.GossipBatchByTransactionIdRequest( ids=["123"], time_to_live=1) # Send BatchByTransaciontIdRequest for txn "123" and add it to the # pending request cache testResponder.batch_request_handler.handle( "Connection_2", request_message.SerializeToString()) testResponder.assert_request_pending(requested_id="123", connection_id="Connection_2") # Send Batch Response that contains the batch that has txn "123" testResponder.batch_response_handler.handle( "Connection_1", (batch, response_message.SerializeToString())) # Handle the the BatchResponse Message. Since Connection_2 had # requested the txn_id in the batch but it could not be fulfilled at # that time of the request the received BatchResponse is forwarded to # Connection_2 testResponder.assert_message_sent( connection_id="Connection_2", message_type=validator_pb2.Message.GOSSIP_BATCH_RESPONSE) # The request for transaction_id "123" from "Connection_2" is no # longer pending it should be removed from the pending request cache. testResponder.assert_request_not_pending(requested_id="123")
def handle(self, connection_id, message_content): batch_response = network_pb2.GossipBatchResponse() batch_response.ParseFromString(message_content) batch = batch_pb2.Batch() batch.ParseFromString(batch_response.content) open_request = self._responder.get_request(batch.header_signature) if open_request is None: open_request = [] requests_to_remove = [batch.header_signature] for txn in batch.transactions: requests_by_txn = self._responder.get_request(txn.header_signature) if requests_by_txn is not None: open_request += requests_by_txn requests_to_remove += [txn.header_signature] for connection in open_request: LOGGER.debug("Responding to batch requests: Send %s to %s", batch.header_signature, connection) try: self._gossip.send(validator_pb2.Message.GOSSIP_BATCH_RESPONSE, message_content, connection) except ValueError: LOGGER.debug( "Can't send batch response %s to closed " "connection %s", batch.header_signature, connection) for requested_id in requests_to_remove: self._responder.remove_request(requested_id) return HandlerResult(HandlerStatus.PASS)
def handle(self, connection_id, message_content): batch_request_message = network_pb2.GossipBatchByBatchIdRequest() batch_request_message.ParseFromString(message_content) batch = None batch = self._responder.check_for_batch(batch_request_message.id) node_id = batch_request_message.node_id if batch is None: # No batch found, broadcast original message to other peers # and add to pending requests self._responder.add_request(batch_request_message.id, connection_id) self._gossip.broadcast( batch_request_message, validator_pb2.Message.GOSSIP_BATCH_BY_BATCH_ID_REQUEST, exclude=[connection_id]) else: LOGGER.debug("Responding to batch requests %s", batch.header_signature) batch_response = network_pb2.GossipBatchResponse( content=batch.SerializeToString(), node_id=node_id) self._gossip.send(validator_pb2.Message.GOSSIP_BATCH_RESPONSE, batch_response.SerializeToString(), connection_id) return HandlerResult(status=HandlerStatus.PASS)
def test_responder_batch_response_txn_handler(): """ Test that the ResponderBatchResponseHandler, after receiving a Batch Response, checks to see if the responder has any pending request for that transactions in the batch and forwards the response on to the connection_id that had them. """ testResponder = TestResponder() transaction = transaction_pb2.Transaction(header_signature="123") batch = batch_pb2.Batch(header_signature="abc", transactions=[transaction]) response_message = network_pb2.GossipBatchResponse( content=batch.SerializeToString()) request_message = \ network_pb2.GossipBatchByTransactionIdRequest( ids=["123"], time_to_live=1) # Send BatchByTransaciontIdRequest for txn "123" and add it to the # pending request cache testResponder.batch_request_handler.handle( "Connection_2", request_message.SerializeToString()) # Send Batch Response that contains the batch that has txn "123" testResponder.batch_response_handler.handle( "Connection_1", (batch, response_message.SerializeToString()))
def test_responder_batch_response_handler(): """ Test that the ResponderBatchResponseHandler, after receiving a Batch Response, checks to see if the responder has any pending request for that batch 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() batch = batch_pb2.Batch(header_signature="abc") response_message = network_pb2.GossipBatchResponse( content=batch.SerializeToString()) testResponder.batch_response_handler.handle( "Connection_1", (batch, response_message.SerializeToString())) # request queue. request_message = \ network_pb2.GossipBatchByBatchIdRequest(id="abc", time_to_live=1) testResponder.batch_request_handler.handle( "Connection_2", request_message.SerializeToString()) # Handle the the BatchResponse Message. Since Connection_2 had # requested the batch but it could not be fulfilled at that time of the # request the received BatchResponse is forwarded to Connection_2 testResponder.batch_response_handler.handle( "Connection_1", (batch, response_message.SerializeToString()))
def handle(self, connection_id, message_content): batch_response_message = network_pb2.GossipBatchResponse() batch_response_message.ParseFromString(message_content) batch = Batch() batch.ParseFromString(batch_response_message.content) self._completer.add_batch(batch) return HandlerResult(status=HandlerStatus.PASS)
def handle(self, connection_id, message_content): batch_request_message = network_pb2.GossipBatchByTransactionIdRequest() batch_request_message.ParseFromString(message_content) node_id = batch_request_message.node_id batch = None batches = [] unfound_txn_ids = [] for txn_id in batch_request_message.ids: batch = self._responder.check_for_batch_by_transaction( txn_id) # The txn_id was not found. if batch is None: unfound_txn_ids.append(txn_id) # Check to see if a previous txn was in the same batch. elif batch not in batches: batches.append(batch) batch = None if batches == []: for txn_id in batch_request_message.ids: self._responder.add_request(txn_id, connection_id) self._gossip.broadcast( batch_request_message, validator_pb2.Message. GOSSIP_BATCH_BY_TRANSACTION_ID_REQUEST, exclude=[connection_id]) elif unfound_txn_ids != []: new_request = network_pb2.GossipBatchByTransactionIdRequest() new_request.ids.extend(unfound_txn_ids) new_request.node_id = batch_request_message.node_id for txn_id in unfound_txn_ids: self._responder.add_request(txn_id, connection_id) self._gossip.broadcast( new_request, validator_pb2.Message. GOSSIP_BATCH_BY_TRANSACTION_ID_REQUEST, exclude=[connection_id]) if batches != []: for batch in batches: LOGGER.debug("Responding to batch requests %s", batch.header_signature) batch_response = network_pb2.GossipBatchResponse( content=batch.SerializeToString(), node_id=node_id) self._gossip.send(validator_pb2.Message.GOSSIP_BATCH_RESPONSE, batch_response.SerializeToString(), connection_id) return HandlerResult(status=HandlerStatus.PASS)
def handle(self, connection_id, message_content): batch_request_message = network_pb2.GossipBatchByBatchIdRequest() batch_request_message.ParseFromString(message_content) if batch_request_message.nonce in self._seen_requests: LOGGER.debug("Received repeat GossipBatchByBatchIdRequest 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[batch_request_message.nonce] = \ batch_request_message.id batch = None batch = self._responder.check_for_batch(batch_request_message.id) node_id = batch_request_message.node_id if batch is None: # No batch found, broadcast original message to other peers # and add to pending requests if not self._responder.already_requested(batch_request_message.id): self._gossip.broadcast( batch_request_message, validator_pb2.Message.GOSSIP_BATCH_BY_BATCH_ID_REQUEST, exclude=[connection_id]) else: LOGGER.debug("Batch %s has already been requested", batch_request_message.id) self._responder.add_request(batch_request_message.id, connection_id) else: LOGGER.debug("Responding to batch requests %s", batch.header_signature) batch_response = network_pb2.GossipBatchResponse( content=batch.SerializeToString(), node_id=node_id) self._gossip.send(validator_pb2.Message.GOSSIP_BATCH_RESPONSE, batch_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)
def handle(self, connection_id, message_content): batch_request_message = network_pb2.GossipBatchByBatchIdRequest() batch_request_message.ParseFromString(message_content) if batch_request_message.nonce in self._seen_requests: LOGGER.debug("Received repeat GossipBatchByBatchIdRequest from %s", connection_id) return HandlerResult(HandlerStatus.DROP) batch = None batch = self._responder.check_for_batch(batch_request_message.id) if batch is None: # No batch found, broadcast original message to other peers # and add to pending requests if not self._responder.already_requested(batch_request_message.id): if batch_request_message.time_to_live > 0: time_to_live = batch_request_message.time_to_live batch_request_message.time_to_live = time_to_live - 1 self._gossip.broadcast( batch_request_message, validator_pb2.Message.GOSSIP_BATCH_BY_BATCH_ID_REQUEST, exclude=[connection_id]) self._seen_requests[batch_request_message.nonce] = \ batch_request_message.id self._responder.add_request(batch_request_message.id, connection_id) else: LOGGER.debug("Batch %s has already been requested", batch_request_message.id) self._responder.add_request(batch_request_message.id, connection_id) else: LOGGER.debug("Responding to batch requests %s", batch.header_signature) batch_response = network_pb2.GossipBatchResponse( content=batch.SerializeToString(), ) self._gossip.send(validator_pb2.Message.GOSSIP_BATCH_RESPONSE, batch_response.SerializeToString(), connection_id) return HandlerResult(HandlerStatus.PASS)
def test_responder_batch_response_handler(self): """ Test that the ResponderBatchResponseHandler, after receiving a Batch Response, checks to see if the responder has any pending request for that batch and forwards the response on to the connection_id that had requested it. """ # The Responder does not have any pending requests for block "ABC" batch = batch_pb2.Batch(header_signature="abc") response_message = network_pb2.GossipBatchResponse( content=batch.SerializeToString()) self.batch_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 batch "abc". This adds it to the pending # request queue. request_message = \ network_pb2.GossipBatchByBatchIdRequest(id="abc") self.batch_request_handler.handle( "Connection_2", request_message.SerializeToString()) self.assert_request_pending( requested_id="abc", connection_id="Connection_2") # Handle the the BatchResponse Message. Since Connection_2 had # requested the batch but it could not be fulfilled at that time of the # request the received BatchResponse is forwarded to Connection_2 self.batch_response_handler.handle( "Connection_1", response_message.SerializeToString()) self.assert_message_sent( connection_id="Connection_2", message_type=validator_pb2.Message.GOSSIP_BATCH_RESPONSE ) # The request for batch "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 test_responder_batch_response_txn_handler(self): """ Test that the ResponderBatchResponseHandler, after receiving a Batch Response, checks to see if the responder has any pending request for that transactions in the batch and forwards the response on to the connection_id that had them. """ transaction = transaction_pb2.Transaction(header_signature="123") batch = batch_pb2.Batch( header_signature="abc", transactions=[transaction]) response_message = network_pb2.GossipBatchResponse( content=batch.SerializeToString()) request_message = \ network_pb2.GossipBatchByTransactionIdRequest( ids=["123"]) # Send BatchByTransaciontIdRequest for txn "123" and add it to the # pending request cache self.batch_request_handler.handle( "Connection_2", request_message.SerializeToString()) self.assert_request_pending( requested_id="123", connection_id="Connection_2") # Send Batch Response that contains the batch that has txn "123" self.batch_response_handler.handle( "Connection_1", response_message.SerializeToString()) # Handle the the BatchResponse Message. Since Connection_2 had # requested the txn_id in the batch but it could not be fulfilled at # that time of the request the received BatchResponse is forwarded to # Connection_2 self.assert_message_sent( connection_id="Connection_2", message_type=validator_pb2.Message.GOSSIP_BATCH_RESPONSE ) # The request for transaction_id "123" from "Connection_2" is no # longer pending it should be removed from the pending request cache. self.assert_request_not_pending(requested_id="123")
def do_responder_batch_response_handler(): batch = batch_pb2.Batch(header_signature="abc") response_message = network_pb2.GossipBatchResponse( content=batch.SerializeToString()) testResponder.batch_response_handler.handle( "Connection_1", (batch, 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 batch "abc". This adds it to the pending # request queue. request_message = \ network_pb2.GossipBatchByBatchIdRequest(id="abc", time_to_live=1) testResponder.batch_request_handler.handle( "Connection_2", request_message.SerializeToString()) testResponder.assert_request_pending(requested_id="abc", connection_id="Connection_2") # Handle the the BatchResponse Message. Since Connection_2 had # requested the batch but it could not be fulfilled at that time of the # request the received BatchResponse is forwarded to Connection_2 testResponder.batch_response_handler.handle( "Connection_1", (batch, response_message.SerializeToString())) testResponder.assert_message_sent( connection_id="Connection_2", message_type=validator_pb2.Message.GOSSIP_BATCH_RESPONSE) # The request for batch "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")
def handle(self, connection_id, message_content): batch_request_message = network_pb2.GossipBatchByTransactionIdRequest() batch_request_message.ParseFromString(message_content) if batch_request_message.nonce in self._seen_requests: LOGGER.debug( "Received repeat GossipBatchByTransactionIdRequest" " from %s", connection_id) return HandlerResult(HandlerStatus.DROP) batch = None batches = [] unfound_txn_ids = [] not_requested = [] for txn_id in batch_request_message.ids: batch = self._responder.check_for_batch_by_transaction(txn_id) # The txn_id was not found. if batch is None: unfound_txn_ids.append(txn_id) if not self._responder.already_requested(txn_id): not_requested.append(txn_id) else: LOGGER.debug( "Batch containing Transaction %s has already " "been requested", txn_id) # Check to see if a previous txn was in the same batch. elif batch not in batches: batches.append(batch) batch = None if batches == [] and len(not_requested) == \ len(batch_request_message.ids): if batch_request_message.time_to_live > 0: time_to_live = batch_request_message.time_to_live batch_request_message.time_to_live = time_to_live - 1 self._gossip.broadcast(batch_request_message, validator_pb2.Message. GOSSIP_BATCH_BY_TRANSACTION_ID_REQUEST, exclude=[connection_id]) self._seen_requests[batch_request_message.nonce] = \ batch_request_message.ids for txn_id in batch_request_message.ids: self._responder.add_request(txn_id, connection_id) elif unfound_txn_ids != []: if not_requested != []: if batch_request_message.time_to_live > 0: self._seen_requests[batch_request_message.nonce] = \ batch_request_message.ids new_request = \ network_pb2.GossipBatchByTransactionIdRequest() # only request batches we have not requested already new_request.ids.extend(not_requested) # Keep same nonce as original message new_request.nonce = batch_request_message.nonce time_to_live = batch_request_message.time_to_live new_request.time_to_live = time_to_live - 1 self._gossip.broadcast( new_request, validator_pb2.Message. GOSSIP_BATCH_BY_TRANSACTION_ID_REQUEST, exclude=[connection_id]) # Add all requests to responder for txn_id in unfound_txn_ids: self._responder.add_request(txn_id, connection_id) else: # Add all requests to responder for txn_id in unfound_txn_ids: self._responder.add_request(txn_id, connection_id) if batches != []: for batch in batches: LOGGER.debug("Responding to batch requests %s", batch.header_signature) batch_response = network_pb2.GossipBatchResponse( content=batch.SerializeToString(), ) self._gossip.send(validator_pb2.Message.GOSSIP_BATCH_RESPONSE, batch_response.SerializeToString(), connection_id) return HandlerResult(HandlerStatus.PASS)