Esempio 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):
        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)
Esempio n. 3
0
    def _generate_batch(self, payload):
        payload_encoded = payload.encode('utf-8')
        hasher = hashlib.sha512()
        hasher.update(payload_encoded)

        header = TransactionHeader()
        header.batcher_pubkey = self.public_key
        # txn.dependencies not yet
        header.family_name = 'test'
        header.family_version = '1'
        header.nonce = _generate_id(16)
        header.payload_encoding = "text"
        header.payload_sha512 = hasher.hexdigest().encode()
        header.signer_pubkey = self.public_key

        txn = Transaction()
        header_bytes = header.SerializeToString()
        txn.header = header_bytes
        txn.header_signature = signing.sign(header_bytes, self.signing_key)
        txn.payload = payload_encoded

        batch_header = BatchHeader()
        batch_header.signer_pubkey = self.public_key
        batch_header.transaction_ids.extend([txn.header_signature])

        batch = Batch()
        header_bytes = batch_header.SerializeToString()
        batch.header = header_bytes
        batch.header_signature = signing.sign(header_bytes, self.signing_key)
        batch.transactions.extend([txn])
        return batch
Esempio n. 4
0
    def handle(self, connection_id, message_content):
        gossip_message = network_pb2.GossipMessage()
        gossip_message.ParseFromString(message_content)
        if gossip_message.content_type == network_pb2.GossipMessage.BLOCK:
            block = Block()
            block.ParseFromString(gossip_message.content)
            LOGGER.debug("CompleterGossipHandler: BLOCK=%s",
                         block.header_signature[:8])
            self._completer.add_block(block)
        elif gossip_message.content_type == network_pb2.GossipMessage.BATCH:
            batch = Batch()
            batch.ParseFromString(gossip_message.content)
            #candidate_id = gossip_message.candidate_id.hex()
            LOGGER.debug("CompleterGossipHandler: NEW BATCH=%s ",
                         batch.header_signature[:8])
            # works in case batch from another node
            self._completer.add_batch(batch)

        elif gossip_message.content_type == network_pb2.GossipMessage.BATCHES:
            batches = BatchList()
            batches.ParseFromString(gossip_message.content)
            candidate_id = batches.candidate_id.hex()
            num = len(batches.batches)
            #LOGGER.debug("CompleterGossipHandler: NEW BATCHES=%s candidate_id=%s", batches,candidate_id[:8])

            block_num = batches.block_num
            for batch in batches.batches:
                LOGGER.debug(" => NEW BATCH[%s]=%s candidate_id=%s.%s", num,
                             batch.header_signature[:8], block_num,
                             candidate_id[:8])
                self._completer.add_batch(batch,
                                          (candidate_id, block_num, num))

        return HandlerResult(status=HandlerStatus.PASS)
Esempio n. 5
0
    def handle(self, connection_id, message_content):
        gossip_message = network_pb2.GossipMessage()
        gossip_message.ParseFromString(message_content)
        if gossip_message.content_type == "BLOCK":
            block = Block()
            block.ParseFromString(gossip_message.content)
            if not is_valid_block(block):
                LOGGER.debug("block's batches structure is invalid: %s",
                             block.header_signature)
                return HandlerResult(status=HandlerStatus.DROP)

            LOGGER.debug("block passes batch structure verification %s",
                         block.header_signature)
            return HandlerResult(status=HandlerStatus.PASS)
        elif gossip_message.content_type == "BATCH":
            batch = Batch()
            batch.ParseFromString(gossip_message.content)
            if not is_valid_batch(batch):
                LOGGER.debug("batch structure is invalid: %s",
                             batch.header_signature)
                return HandlerResult(status=HandlerStatus.DROP)

            LOGGER.debug("batch passes structure verification %s",
                         batch.header_signature)
            return HandlerResult(status=HandlerStatus.PASS)

        return HandlerResult(status=HandlerStatus.PASS)
    def test_publish(self, args=sys.argv[1:]):

        gossip = GossipMock()

        LOGGER.info(self.blocks)
        publisher = BlockPublisher(
            consensus=TestModePublisher(),
            transaction_executor=TransactionExecutorMock(),
            send_message=gossip.send_message,
            squash_handler=None)

        LOGGER.info("1")

        # initial load of existing state
        publisher.on_chain_updated(self.blocks.chain_head.block, [], [])

        LOGGER.info("2")
        # repeat as necessary
        batch = Batch()
        publisher.on_batch_received(batch)
        LOGGER.info("3")
        # current dev_mode consensus always claims blocks when asked.
        # this will be called on a polling every so often or possibly triggered
        # by events in the consensus it's self ... TBD
        publisher.on_check_publish_block()
        LOGGER.info("4")
        LOGGER.info(self.blocks)

        # repeat as necessary
        batch = Batch()
        publisher.on_batch_received(batch)

        publisher.on_check_publish_block()

        LOGGER.info(self.blocks)
Esempio n. 7
0
    def test_publish(self):

        LOGGER.info(self.blocks)
        publisher = BlockPublisher(
            consensus=TestModePublisher(),
            transaction_executor=MockTransactionExecutor(),
            block_sender=self.block_sender,
            squash_handler=None,
            chain_head=self.blocks.chain_head)

        # initial load of existing state
        publisher.on_chain_updated(self.blocks.chain_head, [], [])

        # repeat as necessary
        batch = Batch()
        publisher.on_batch_received(batch)
        # current dev_mode consensus always claims blocks when asked.
        # this will be called on a polling every so often or possibly triggered
        # by events in the consensus it's self ... TBD
        publisher.on_check_publish_block()
        LOGGER.info(self.blocks)

        # repeat as necessary
        batch = Batch()
        publisher.on_batch_received(batch)

        publisher.on_check_publish_block()

        LOGGER.info(self.blocks)
    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)
Esempio n. 9
0
    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)
Esempio n. 10
0
def gossip_batch_response_preprocessor(message_content_bytes):
    batch_response = GossipBatchResponse()
    batch_response.ParseFromString(message_content_bytes)
    batch = Batch()
    batch.ParseFromString(batch_response.content)

    content = batch, message_content_bytes

    return PreprocessorResult(content=content)
Esempio n. 11
0
 def test_no_batch(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")
     message = GossipMessage(content_type=GossipMessage.BATCH,
                             content=batch.SerializeToString())
     handler_status = self.handler.handle(
         "connection_id", message.SerializeToString())
     self.assertEqual(handler_status.status, HandlerStatus.PASS)
Esempio n. 12
0
    def run(self):
        while True:
            if self._exit:
                return
            try:
                request = self.incoming_msg_queue.get(block=False)
                if request.content_type == "Block":
                    try:
                        block = Block()
                        block.ParseFromString(request.content)
                        status = self.validate_block(block)
                        if status:
                            self.outgoing_msg_queue.put_nowait(request)
                            with self.out_condition:
                                self.out_condition.notify_all()
                                LOGGER.info("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.outgoing_msg_queue.put_nowait(request)
                            with self.out_condition:
                                self.out_condition.notify_all()
                        else:
                            LOGGER.info("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.outgoing_msg_queue.put_notwait(request)
                    with self.out_condition:
                        self.out_condition.notify_all()

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

            except queue.Empty:
                with self.in_condition:
                    self.in_condition.wait()
Esempio n. 13
0
 def handle(self, connection_id, message_content):
     gossip_message = network_pb2.GossipMessage()
     gossip_message.ParseFromString(message_content)
     if gossip_message.content_type == network_pb2.GossipMessage.BLOCK:
         block = Block()
         block.ParseFromString(gossip_message.content)
         self._completer.add_block(block)
     elif gossip_message.content_type == network_pb2.GossipMessage.BATCH:
         batch = Batch()
         batch.ParseFromString(gossip_message.content)
         self._completer.add_batch(batch)
     return HandlerResult(status=HandlerStatus.PASS)
    def handle(self, connection_id, message_content):
        batch_response_message = GossipBatchResponse()
        batch_response_message.ParseFromString(message_content)

        batch = Batch()
        batch.ParseFromString(batch_response_message.content)
        if not is_valid_batch(batch):
            LOGGER.debug("requested batch's structure is invalid: %s",
                         batch.header_signature)
            return HandlerResult(status=HandlerStatus.DROP)

        return HandlerResult(status=HandlerStatus.PASS)
Esempio n. 15
0
    def run(self):
        if self.incoming_msg_queue is None or self.condition is None:
            LOGGER.warning("Dispatcher can not be used if incoming_msg_queue "
                           "or condition is not set.")
            return

        while True:
            if self._exit:
                return

            try:
                request = self.incoming_msg_queue.get(block=False)
                if request.content_type == "Block":
                    try:
                        block = Block()
                        block.ParseFromString(request.content)
                        LOGGER.debug("Block given to Completer %s",
                                     block.header_signature)
                        self.completer_queue.put_nowait(block)
                        with self.completer_conditon:
                            self.completer_conditon.notify_all()
                    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)
                        self.completer.add_batch(batch)
                        self.on_batch_received(batch)

                    except DecodeError as e:
                        LOGGER.warning(
                            "Problem decoding GossipMessage for "
                            "Batch, %s", e)

                elif request.content_type == "BlockRequest":
                    block_id = str(request.content, "utf-8")
                    self.on_block_requested(block_id)

                elif request.content_type == "Test":
                    LOGGER.debug("Dispatch Handle Test")

            except queue.Empty:
                with self.condition:
                    self.condition.wait()
Esempio n. 16
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)
    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)
Esempio n. 18
0
    def create_batch(self, block_info):
        payload = BlockInfoTxn(block=block_info).SerializeToString()
        public_key = self._signer.get_public_key().as_hex()
        header = TransactionHeader(
            signer_public_key=public_key,
            family_name=FAMILY_NAME,
            family_version=FAMILY_VERSION,
            inputs=[CONFIG_ADDRESS, BLOCK_INFO_NAMESPACE],
            outputs=[CONFIG_ADDRESS, BLOCK_INFO_NAMESPACE],
            dependencies=[],
            payload_sha512=hashlib.sha512(payload).hexdigest(),
            batcher_public_key=public_key,
        ).SerializeToString()

        transaction_signature = self._signer.sign(header)

        transaction = Transaction(
            header=header,
            payload=payload,
            header_signature=transaction_signature,
        )

        header = BatchHeader(
            signer_public_key=public_key,
            transaction_ids=[transaction_signature],
        ).SerializeToString()

        batch_signature = self._signer.sign(header)

        return Batch(
            header=header,
            transactions=[transaction],
            header_signature=batch_signature,
        )
Esempio n. 19
0
    def handle(self, connection_id, message_content):
        batch_response_message = GossipBatchResponse()
        batch_response_message.ParseFromString(message_content)

        batch = Batch()
        batch.ParseFromString(batch_response_message.content)
        status = validate_batch(batch)

        if status is True:
            LOGGER.debug("requested batch passes signature verification %s",
                         batch.header_signature)
            return HandlerResult(status=HandlerStatus.PASS)
        else:
            LOGGER.debug("requested batch's signature is invalid: %s",
                         batch.header_signature)
            return HandlerResult(status=HandlerStatus.DROP)
Esempio n. 20
0
    def _create_batches(self, batch_count, txn_count,
                        missing_dep=False):

        batch_list = []

        for i in range(batch_count):
            txn_list = self._create_transactions(txn_count,
                                                 missing_dep=missing_dep)
            txn_sig_list = [txn.header_signature for txn in txn_list]

            batch_header = BatchHeader(signer_pubkey=self.public_key)
            batch_header.transaction_ids.extend(txn_sig_list)

            header_bytes = batch_header.SerializeToString()


            signature = signing.sign(
                header_bytes,
                self.private_key)

            batch = Batch(header=header_bytes,
                          transactions=txn_list,
                          header_signature=signature)

            batch_list.append(batch)

        return batch_list
Esempio n. 21
0
    def _create_batches(self,
                        batch_count,
                        txn_count,
                        valid_batch=True,
                        valid_txn=True,
                        valid_structure=True,
                        valid_batcher=True):

        batch_list = []

        for i in range(batch_count):
            txn_list = self._create_transactions(txn_count, valid_txn,
                                                 valid_batcher)
            txn_sig_list = [txn.header_signature for txn in txn_list]
            if not valid_structure:
                txn_sig_list.pop()

            batch_header = BatchHeader(signer_pubkey=self.public_key)
            batch_header.transaction_ids.extend(txn_sig_list)

            header_bytes = batch_header.SerializeToString()

            if valid_batch:
                signature = signing.sign(header_bytes, self.private_key)
            else:
                signature = "bad_signature"

            batch = Batch(header=header_bytes,
                          transactions=txn_list,
                          header_signature=signature)

            batch_list.append(batch)

        return batch_list
    def _generate_batch(self, txn_count=2, missing_deps=False, txns=None):
        if txns is None:
            txns = []

        if txn_count != 0:
            txns += [
                self.generate_transaction('txn_' + str(i))
                for i in range(txn_count)
            ]

        if missing_deps:
            target_txn = txns[-1]
            txn_missing_deps = self.generate_transaction(
                payload='this one has a missing dependency',
                deps=[target_txn.header_signature])
            # replace the targeted txn with the missing deps txn
            txns[-1] = txn_missing_deps

        batch_header = BatchHeader(
            signer_public_key=self.signer.get_public_key().as_hex(),
            transaction_ids=[txn.header_signature
                             for txn in txns]).SerializeToString()

        batch = Batch(header=batch_header,
                      header_signature=self.signer.sign(batch_header),
                      transactions=txns)

        return batch
Esempio n. 23
0
    def handle(self, connection_id, message_content):
        batch_response_message = GossipBatchResponse()
        batch_response_message.ParseFromString(message_content)

        batch = Batch()
        batch.ParseFromString(batch_response_message.content)
        if batch.header_signature in self._seen_cache:
            self._batch_dropped_count.inc()
            return HandlerResult(status=HandlerStatus.DROP)

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

        self._seen_cache[batch.header_signature] = None
        return HandlerResult(status=HandlerStatus.PASS)
Esempio n. 24
0
    def get_batch(self, batch_id):
        """
        Check to see if the requested batch_id is in the current chain. If so,
        find the batch with the batch_id and return it. This is done by
        finding the block and searching for the batch.

        :param batch_id (string): The id of the batch requested.
        :return:
        The batch with the batch_id.
        """

        payload = self._get_data_by_id(batch_id, 'commit_store_get_batch')

        batch = Batch()
        batch.ParseFromString(payload)

        return batch
Esempio n. 25
0
    def test_publish_block(self):
        """
        Test that the Journal will produce blocks and consume those blocks
        to extend the chain.
        :return:
        """
        # construction and wire the journal to the
        # gossip layer.

        LOGGER.info("test_publish_block")
        block_store = {}
        journal = None
        try:
            journal = Journal(
                consensus=test_mode_consensus,
                block_store=block_store,
                send_message=self.gossip.send_message,
                transaction_executor=self.txn_executor,
                squash_handler=None,
                first_state_root="000000")

            self.gossip.on_batch_received = \
                journal.on_batch_received
            self.gossip.on_block_received = \
                journal.on_block_received
            self.gossip.on_block_request = \
                journal.on_block_request

            journal.start()

            # feed it a batch
            batch = Batch()
            journal.on_batch_received(batch)

            # wait for a block message to arrive should be soon
            to = TimeOut(2)
            while len(self.gossip.messages) == 0:
                time.sleep(0.1)

            LOGGER.info("Batches: %s", self.gossip.messages)
            self.assertTrue(len(self.gossip.messages) != 0)

            block = self.gossip.messages[0]
            # dispatch the message
            self.gossip.dispatch_messages()

            # wait for the chain_head to be updated.
            to = TimeOut(2)
            while block_store['chain_head_id'] != block.header_signature:
                time.sleep(0.1)

            self.assertTrue(block_store['chain_head_id'] ==
                            block.header_signature)

        finally:
            if journal is not None:
                journal.stop()
Esempio n. 26
0
    def handle(self, connection_id, message_content):
        batch_response_message = GossipBatchResponse()
        batch_response_message.ParseFromString(message_content)
        batch = Batch()
        batch.ParseFromString(batch_response_message.content)

        batch_id = batch.header_signature

        if not self._has_open_requests(batch_id) and self._has_batch(batch_id):
            LOGGER.debug('Drop duplicate batch: %s', batch_id)
            return HandlerResult(HandlerStatus.RETURN)

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

        return HandlerResult(HandlerStatus.RETURN_AND_PASS,
                             message_out=ack,
                             message_type=validator_pb2.Message.NETWORK_ACK)
Esempio n. 27
0
def _make_mock_batch(self, batch_id='batch_id'):
    txn = _make_mock_transaction(batch_id)

    header = BatchHeader(signer_pubkey='pubkey',
                         transaction_ids=[txn.header_signature])

    return Batch(header=header.SerializeToString(),
                 header_signature=batch_id,
                 transactions=[txn])
Esempio n. 28
0
 def test_no_batch(self):
     """
     Test that if the batch has not been received recently,
     the gossip message is passed.
     """
     batch = Batch(header_signature="Batch1")
     handler_status = self.handler.handle("connection_id",
                                          (batch, GossipMessage.BATCH, 2))
     self.assertEqual(handler_status.status, HandlerStatus.PASS)
Esempio n. 29
0
 def test_no_batch(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")
     handler_status = self.handler.handle("connection_id",
                                          (batch, GossipMessage.BATCH, 2))
     self.assertEqual(handler_status.status, HandlerStatus.PASS)
Esempio n. 30
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)