示例#1
0
    def test_serialize_from_objects(self):
        """
        Tests that serialize/deserialize are inverse operations with from_objects factory function
        """
        sk, vk = wallet.new()
        message = self._default_msg()

        env = Envelope.create_from_message(message=message,
                                           signing_key=sk,
                                           verifying_key=vk)

        self.assertEqual(env, Envelope.from_bytes(env.serialize()))
示例#2
0
    def create(cls,
               envelope: Envelope = None,
               envelope_binary: bytes = None,
               **kwargs):
        assert not (
            envelope and envelope_binary
        ), "Either envelope or envelope_binary should be passed in (not both)"

        cmd = reactor_capnp.ReactorCommand.new_message()

        if envelope:
            assert isinstance(
                envelope,
                Envelope), "'envelope' kwarg must be an Envelope instance"
            cmd.envelope.data = envelope.serialize()
        if envelope_binary:
            assert isinstance(envelope_binary,
                              bytes), "'envelope_binary' must be bytes"
            cmd.envelope.data = envelope_binary

        cmd.init('kwargs', len(kwargs))
        for i, key in enumerate(kwargs):
            cmd.kwargs[i].key, cmd.kwargs[i].value = str(key), str(kwargs[key])

        return cls.from_data(cmd)
示例#3
0
    def _validate_envelope(self, envelope_binary: bytes, header: str) -> Union[None, Envelope]:
        # TODO return/raise custom exceptions in this instead of just logging stuff and returning none

        # Deserialize envelope
        env = None
        try:
            env = Envelope.from_bytes(envelope_binary)
        except Exception as e:
            self.log.error("Error deserializing envelope: {}".format(e))
            return None

        # Check seal
        if not env.verify_seal():
            self.log.error("Seal could not be verified for envelope {}".format(env))
            return None

        # If header is not none (meaning this is a ROUTE msg with an ID frame), then verify that the ID frame is
        # the same as the vk on the seal
        if header and (header != env.seal.verifying_key):
            self.log.error("Header frame {} does not match seal's vk {}\nfor envelope {}"
                           .format(header, env.seal.verifying_key, env))
            return None

        # Make sure we haven't seen this message before
        if env.meta.uuid in Executor._recently_seen:
            self.log.debug("Duplicate envelope detect with UUID {}. Ignoring.".format(env.meta.uuid))
            return None

        # TODO -- checks timestamp to ensure this envelope is recv'd in a somewhat reasonable time (within N seconds)

        # If none of the above checks above return None, this envelope should be good
        return env
示例#4
0
    def request(self,
                url: str,
                reply_uuid: str,
                envelope: Envelope,
                timeout=0):
        self.log.spam("requesting /w reply uuid {} and env {}".format(
            reply_uuid, envelope))
        assert url in self.dealers, "Attempted to make request to url {} that is not in self.dealers {}"\
            .format(url, self.dealers)

        reply_uuid = int(reply_uuid)
        timeout = float(timeout)

        self.log.spam(
            "Composing request to url {}\ntimeout: {}\nenvelope: {}".format(
                url, timeout, envelope))

        if timeout > 0:
            assert reply_uuid not in self.expected_replies, "Reply UUID is already in expected replies"
            self.log.spam("Adding timeout of {} for reply uuid {}".format(
                timeout, reply_uuid))
            self.expected_replies[reply_uuid] = self.loop.call_later(
                timeout, self._timeout, url, envelope, reply_uuid)

        self.dealers[url][_SOCKET].send_multipart([envelope.serialize()])
示例#5
0
    def send_pub(self, filter: str, envelope: bytes):
        assert isinstance(filter, str), "'id' arg must be a string"
        assert isinstance(envelope, bytes), "'envelope' arg must be bytes"
        assert len(self.pubs) > 0, "Attempted to publish data but publisher socket(s) is not configured"

        for url in self.pubs:
            self.log.debug("Publishing to URL {} with envelope: {}".format(url, Envelope.from_bytes(envelope)))
            # self.log.info("Publishing to... {}".format(url))
            self.pubs[url].send_multipart([filter.encode(), envelope])
示例#6
0
    def send_pub(self, url: str, filter: str, data: bytes):
        assert isinstance(
            filter, str), "'filter' arg must be a string not {}".format(filter)
        assert isinstance(data, bytes), "'envelope' arg must be bytes"
        assert url in self.pubs, "Attempted to pub to URL {} that is not in self.pubs {}".format(
            url, self.pubs)

        self.log.spam("Publishing to URL {} with envelope: {}".format(
            url, Envelope.from_bytes(data)))
        self.pubs[url].send_multipart([filter.encode(), data])
示例#7
0
    def _package_msg(self, msg: MessageBase) -> Envelope:
        """
        Convenience method to package a message into an envelope
        :param msg: The MessageBase instance to package
        :return: An Envelope instance
        """
        assert type(msg) is not Envelope, "Attempted to package a 'message' that is already an envelope"
        assert issubclass(type(msg), MessageBase), "Attempted to package a message that is not a MessageBase subclass"

        return Envelope.create_from_message(message=msg, signing_key=self.signing_key, verifying_key=self.verifying_key)
示例#8
0
    def _recv_reply_env(self, header: str, envelope: Envelope):
        self.log.debug("Recv REPLY envelope with header {} and envelope {}".format(header, envelope))

        reply_uuid = envelope.meta.uuid
        if reply_uuid in self.expected_replies:
            self.log.debug("Removing reply with uuid {} from expected replies".format(reply_uuid))
            self.expected_replies[reply_uuid].cancel()
            del(self.expected_replies[reply_uuid])

        self.call_on_mp(callback=StateInput.INPUT, header=header, envelope_binary=envelope.serialize())
示例#9
0
    def test_create_from_message(self):
        """
        Tests create_from_message with valid args (no vk passed) creates an envelope valid signature and expected fields
        """
        sk, vk = wallet.new()
        msg = self._default_msg()

        env = Envelope.create_from_message(message=msg, signing_key=sk)

        self.assertTrue(env.verify_seal())
        self.assertEqual(env.message, msg)
        self.assertEqual(env.seal.verifying_key, vk)
示例#10
0
    def test_create_with_envelope(self):
        """
        Tests creating a message with an envelope produces an object with the expected properties
        """
        sk, vk = wallet.new()
        tx = StandardTransactionBuilder.random_tx()
        sender = 'me'
        env = Envelope.create_from_message(message=tx, signing_key=sk)

        cmd = ReactorCommand.create_cmd('some_cls', 'some_func', envelope=env)

        self.assertTrue(ReactorCommand.envelope, env)
示例#11
0
    def _package_reply(self, reply: MessageBase, req_env: Envelope) -> Envelope:
        """
        Convenience method to create a reply envelope. The difference between this func and _package_msg, is that
        in the reply envelope the UUID must be the hash of the original request's uuid (not some randomly generated int)
        :param reply: The reply message (an instance of MessageBase)
        :param req_env: The original request envelope (an instance of Envelope)
        :return: An Envelope instance
        """
        self.log.debug("Creating REPLY envelope with msg type {} for request envelope {}".format(type(reply), req_env))
        request_uuid = req_env.meta.uuid
        reply_uuid = EnvelopeAuth.reply_uuid(request_uuid)

        return Envelope.create_from_message(message=reply, signing_key=self.signing_key,
                                            verifying_key=self.verifying_key, uuid=reply_uuid)
示例#12
0
    def test_create_from_objects(self):
        """
        Test that create returns an object with expected properties
        """
        seal = self._default_seal()
        meta = self._default_meta()
        message = self._default_msg()

        env = Envelope._create_from_objects(seal=seal,
                                            meta=meta,
                                            message=message.serialize())

        self.assertEqual(env.seal, seal)
        self.assertEqual(env.meta, meta)
        self.assertEqual(env.message, message)
示例#13
0
    def test_lazy_serialize(self):
        """
        Tests that creating an envelope from_bytes does not try to repack the underlying struct when serialize is called.
        This is b/c the serialize() func should be 'cached' with the binary data passed into from_bytes
        """
        sk, vk = wallet.new()
        message = self._default_msg()

        env = Envelope.create_from_message(message=message,
                                           signing_key=sk,
                                           verifying_key=vk)
        env_binary = env.serialize()

        clone = Envelope.from_bytes(env_binary)

        clone._data = MagicMock()

        clone_binary = clone.serialize(
        )  # this should not pack the capnp struct (_data) again

        # The Envelope Kitchen Sink lol -- make sure no serialization related API is called
        clone._data.as_builder.assert_not_called()
        clone._data.to_bytes_packed.assert_not_called()
        clone._data.to_bytes.assert_not_called()
示例#14
0
 def send_pub_env(self,
                  filter: str,
                  envelope: Envelope,
                  protocol: str = 'tcp',
                  port: int = DEFAULT_PUB_PORT,
                  ip: str = ''):
     """
     Publish envelope with filter frame 'filter'.
     :param filter: A string to use as the filter frame
     :param envelope: An instance of Envelope
     """
     ip = ip or self.ip
     url = self._build_url(protocol=protocol, port=port, ip=ip, vk='')
     self.manager.executors['SubPubExecutor'].send_pub(
         url=url, filter=filter, data=envelope.serialize())
示例#15
0
    def test_validate_bad_seal(self):
        meta = self._default_meta()
        message = self._default_msg()
        sk, vk = wallet.new()
        sk2, vk2 = wallet.new()

        signature = EnvelopeAuth.seal(signing_key=sk,
                                      meta=meta,
                                      message=message)

        seal = Seal.create(signature=signature, verifying_key=vk2)

        env = Envelope._create_from_objects(seal=seal,
                                            meta=meta,
                                            message=message.serialize())

        self.assertFalse(env.verify_seal())
示例#16
0
    def test_verify_seal(self):
        """
        Tests verify seal with a valid signature
        """
        meta = self._default_meta()
        message = self._default_msg()
        sk, vk = wallet.new()

        signature = EnvelopeAuth.seal(signing_key=sk,
                                      meta=meta,
                                      message=message)
        seal = Seal.create(signature=signature, verifying_key=vk)

        env = Envelope.create_from_message(message=message,
                                           signing_key=sk,
                                           verifying_key=vk)

        self.assertTrue(env.verify_seal())
示例#17
0
    def test_validate_envelope(self):
        """
        Tests validate envelope function
        """
        meta = self._default_meta()
        message = self._default_msg()
        sk, vk = wallet.new()

        signature = EnvelopeAuth.seal(signing_key=sk,
                                      meta=meta,
                                      message=message)
        seal = Seal.create(signature=signature, verifying_key=vk)

        env = Envelope._create_from_objects(seal=seal,
                                            meta=meta,
                                            message=message.serialize())

        env.validate()
示例#18
0
    def test_verify_seal_invalid(self):
        """
        Tests verifying a seal with an invalid signature
        """
        meta = self._default_meta()
        message = self._default_msg()
        sk, vk = wallet.new()
        sk_prime = 'A' * 64

        signature = EnvelopeAuth.seal(signing_key=sk_prime,
                                      meta=meta,
                                      message=message)
        seal = Seal.create(signature=signature, verifying_key=vk)

        env = Envelope._create_from_objects(seal=seal,
                                            meta=meta,
                                            message=message.serialize())

        env.verify_seal()
示例#19
0
    def test_create_from_message_bad_keypair(self):
        """
        test create_from_message passing in sk does and incorrect vk
        """
        sk, vk = wallet.new()
        sk1, vk1 = wallet.new()
        msg = self._default_msg()
        sender = 'dat boi'

        env = Envelope.create_from_message(message=msg,
                                           signing_key=sk,
                                           verifying_key=vk)  # no error

        self.assertEqual(env.seal.verifying_key, vk)

        self.assertRaises(Exception, Envelope.create_from_message, msg, sk,
                          sender, vk1)

        self.assertNotEqual(env.seal.verifying_key, vk1)
示例#20
0
 def _recv_request_env(self, header: str, envelope: Envelope):
     self.log.debug("Recv REQUEST envelope with header {} and envelope {}".format(header, envelope))
     self.call_on_mp(callback=StateInput.REQUEST, header=header, envelope_binary=envelope.serialize())
示例#21
0
 def _recv_pub_env(self, header: str, envelope: Envelope):
     self.log.debug("Recv'd pub envelope with header {} and env {}".format(header, envelope))
     self.call_on_mp(callback=StateInput.INPUT, envelope_binary=envelope.serialize())
示例#22
0
 def envelope(self):
     if self._data.envelope.which() == 'unset':
         return None
     else:
         return Envelope.from_bytes(self._data.envelope.data)