Example #1
0
 def test_unicode_errormessage(self):
     """
     Unicode arguments in ApplicationError will not raise an exception when
     the error_message method is called.
     """
     error = ApplicationError(u"some.url", u"\u2603")
     print(error.error_message())
     self.assertIn(u"\u2603", error.error_message())
 def test_unicode_errormessage(self):
     """
     Unicode arguments in ApplicationError will not raise an exception when
     the error_message method is called.
     """
     error = ApplicationError(u"some.url", u"\u2603")
     if PY3:
         # on py27-tw189: exceptions.UnicodeEncodeError: 'ascii' codec can't encode character u'\u2603' in position 10: ordinal not in
         print(error.error_message())
     self.assertIn(u"\u2603", error.error_message())
Example #3
0
    def session_flush_testaments(self, scope=u"destroyed", details=None):
        """
        Flush the testaments of a given scope.

        :param scope: The scope to flush, either "detatched" or "destroyed".
        :type scope: str

        :returns: Number of flushed testament events.
        :rtype: int
        """
        session = self._router._session_id_to_session[details.caller]

        if scope not in [u"destroyed", u"detatched"]:
            raise ApplicationError(u"wamp.error.testament_error",
                                   u"scope must be destroyed or detatched")

        flushed = len(session._testaments[scope])

        session._testaments[scope] = []

        return flushed
Example #4
0
    def subscription_get(self, subscription_id):
        """
        Get subscription details.

        :param subscription_id: The ID of the subscription to retrieve.
        :type subscription_id: int

        :returns: The subscription details.
        :rtype: dict
        """
        subscription = self._router._broker._subscription_map.get_observation_by_id(subscription_id)
        if subscription and not is_protected_uri(subscription.uri):
            subscription_details = {
                'id': subscription.id,
                'created': subscription.created,
                'uri': subscription.uri,
                'match': subscription.match,
            }
            return subscription_details
        else:
            raise ApplicationError(ApplicationError.NO_SUCH_SUBSCRIPTION, message="no subscription with ID {} exists on this broker".format(subscription_id))
    def subscription_list_subscribers(self, subscription_id):
        """
        Retrieve list of subscribers (WAMP session IDs) subscribed on (attached to) a subscription.

        :param subscription_id: The ID of the subscription to get subscribers for.
        :type subscription_id: int

        :returns: A list of WAMP session IDs of subscribers currently attached to the subscription.
        :rtype: list
        """
        subscription = self._router._broker._subscription_map.get_observation_by_id(subscription_id)
        if subscription and not is_protected_uri(subscription.uri):
            session_ids = []
            for subscriber in subscription.observers:
                session_ids.append(subscriber._session_id)
            return session_ids
        else:
            raise ApplicationError(
                ApplicationError.NO_SUCH_SUBSCRIPTION,
                u'no subscription with ID {} exists on this broker'.format(subscription_id),
            )
    def registration_list_callees(self, registration_id):
        """
        Retrieve list of callees (WAMP session IDs) registered on (attached to) a registration.

        :param registration_id: The ID of the registration to get callees for.
        :type registration_id: int

        :returns: A list of WAMP session IDs of callees currently attached to the registration.
        :rtype: list
        """
        registration = self._router._dealer._registration_map.get_observation_by_id(registration_id)
        if registration and not is_protected_uri(registration.uri):
            session_ids = []
            for callee in registration.observers:
                session_ids.append(callee._session_id)
            return session_ids
        else:
            raise ApplicationError(
                ApplicationError.NO_SUCH_REGISTRATION,
                u'no registration with ID {} exists on this dealer'.format(registration_id),
            )
Example #7
0
    def get_user_by_pubkey(self, pubkey, details=None):
        """
        Get a user by public key.

        :param pubkey: Public key of the user to retrieve.
        :type pubkey: str

        :param details: Call details
        :type details: :class:`autobahn.wamp.types.CallDetails`
        """
        assert type(pubkey) == str
        assert details is None or isinstance(details, CallDetails)

        with self.db.begin() as txn:
            user_id = self.schema.idx_users_by_pubkey[txn, pubkey]
            if user_id:
                user = self.schema.users[txn, user_id]
                assert user
                return user.marshal()
            else:
                raise ApplicationError('crossbar.error.no_such_object', 'no user with pubkey {}'.format(pubkey))
Example #8
0
    def subscription_count_subscribers(self, subscription_id, details=None):
        """
        Retrieve number of subscribers subscribed on (attached to) a subscription.

        :param subscription_id: The ID of the subscription to get the number subscribers for.
        :type subscription_id: int

        :returns: Number of subscribers currently attached to the subscription.
        :rtype: int
        """
        subscription = self._router._broker._subscription_map.get_observation_by_id(
            subscription_id)

        if subscription and is_protected_uri(subscription.uri, details):
            return len(subscription.observers)
        else:
            raise ApplicationError(
                ApplicationError.NO_SUCH_SUBSCRIPTION,
                u'no subscription with ID {} exists on this broker'.format(
                    subscription_id),
            )
Example #9
0
    def registration_count_callees(self, registration_id, details=None):
        """
        Retrieve number of callees registered on (attached to) a registration.

        :param registration_id: The ID of the registration to get the number of callees for.
        :type registration_id: int

        :returns: Number of callees currently attached to the registration.
        :rtype: int
        """
        registration = self._router._dealer._registration_map.get_observation_by_id(
            registration_id)

        if registration and not is_protected_uri(registration.uri, details):
            return len(registration.observers)
        else:
            raise ApplicationError(
                ApplicationError.NO_SUCH_REGISTRATION,
                u'no registration with ID {} exists on this dealer'.format(
                    registration_id),
            )
Example #10
0
    def get_router_component(self, id, details=None):
        """
        Get details about a router component

        :param id: The ID of the component to get
        :type id: str

        :param details: Call details.
        :type details: :class:`autobahn.wamp.types.CallDetails`

        :returns: Details of component
        :rtype: dict
        """
        self.log.debug("{name}.get_router_component({id})",
                       name=self.__class__.__name__,
                       id=id)
        if id in self.components:
            return self.components[id].marshal()
        else:
            raise ApplicationError(u"crossbar.error.no_such_object",
                                   "No component {}".format(id))
Example #11
0
    def get_router_realm_uplinks(self, id, details=None):
        """
        Get uplinks currently running on a realm running on this router worker.

        :param id: The ID of the router realm to list uplinks for.
        :type id: str

        :param details: Call details.
        :type details: autobahn.wamp.types.CallDetails

        :returns: A list of uplinks.
        :rtype: list of dicts
        """
        self.log.debug("{name}.get_router_realm_uplinks",
                       name=self.__class__.__name__)

        if id not in self.realms:
            raise ApplicationError(u"crossbar.error.no_such_object",
                                   "No realm with ID '{}'".format(id))

        return self.realms[id].uplinks.values()
Example #12
0
    def session_add_testament(self, topic, args, kwargs, publish_options=None, scope="destroyed", details=None):
        """
        Add a testament to the current session.

        :param topic: The topic to publish the testament to.
        :type topic: str

        :param args: A list of arguments for the publish.
        :type args: list or tuple

        :param kwargs: A dict of keyword arguments for the publish.
        :type kwargs: dict

        :param publish_options: The publish options for the publish.
        :type publish_options: None or dict

        :param scope: The scope of the testament, either "detached" or
            "destroyed".
        :type scope: str

        :returns: The publication ID.
        :rtype: int
        """
        session = self._router._session_id_to_session[details.caller]

        if scope not in ["destroyed", "detached"]:
            raise ApplicationError("wamp.error.testament_error", "scope must be destroyed or detached")

        pub_id = util.id()

        # Get the publish options, remove some explicit keys
        publish_options = publish_options or {}
        publish_options.pop("acknowledge", None)
        publish_options.pop("exclude_me", None)

        pub = message.Publish(request=pub_id, topic=topic, args=args, kwargs=kwargs, **publish_options)

        session._testaments[scope].append(pub)

        return pub_id
Example #13
0
def populateRoom(name, patId, patName, patSurname, patTitle):
    room = Room.get_or_none(name=name)
    if room is not None:
        patient, created = Patient.get_or_create(patId=patId,
                                                 defaults={
                                                     'name': patName,
                                                     'surname': patSurname,
                                                     'title': patTitle
                                                 })
        if not created:
            patient.name = patName
            patient.surname = patSurname
            patient.title = patTitle
            patient.save()

        oldroom = None
        with db.atomic() as transaction:
            oldroom = Room.get_or_none(patient=patient)
            if oldroom is not None:
                oldroom.patient = None
                oldroom.save()

            room.patient = patient
            room.save()

            if mySession:
                if oldroom is not None:
                    mySession.publish(u"com.eas.room_populated",
                                      unicode(oldroom.name), None)
                mySession.publish(
                    u"com.eas.room_populated", unicode(name), {
                        u"id": unicode(patId),
                        u"name": unicode(patName),
                        u"surname": unicode(patSurname),
                        u"title": unicode(patTitle)
                    })
    else:
        raise ApplicationError(u"com.eas.error.room_not_found", room=name)

    return True
Example #14
0
    def get_trace_data(self,
                       trace_id,
                       from_seq,
                       to_seq=None,
                       limit=None,
                       details=None):
        self.log.debug(
            'get_trace_data(trace_id="{trace_id}", from_seq="{from_seq})", to_seq="{to_seq}", limit="{limit}")',
            trace_id=trace_id,
            from_seq=from_seq,
            to_seq=to_seq,
            limit=limit)

        if trace_id not in self._traces:
            raise ApplicationError(u"crossbar.error.no_such_object",
                                   "No trace with ID '{}'".format(trace_id))

        limit = limit or 100
        if limit > 10000:
            raise Exception('limit too large')

        return self._traces[trace_id].get_data(from_seq, to_seq, limit)
Example #15
0
    def stop_router_transport(self, transport_id, details=None):
        """
        Stop a transport currently running in this router worker.

        :param transport_id: The ID of the transport to stop.
        :type transport_id: str

        :param details: Call details.
        :type details: :class:`autobahn.wamp.types.CallDetails`
        """
        self.log.debug("{name}.stop_router_transport",
                       name=self.__class__.__name__)

        if transport_id not in self.transports or self.transports[
                transport_id].state(
                ) != self.personality.RouterTransport.STATE_STARTED:
            emsg = "Cannot stop transport: no transport with ID '{}' or transport is already stopping".format(
                transport_id)
            self.log.error(emsg)
            raise ApplicationError(u'crossbar.error.not_running', emsg)

        router_transport = self.transports[transport_id]

        self.log.debug("Stopping transport with ID '{transport_id}'",
                       transport_id=transport_id)

        # stop listening ..
        d = router_transport.stop()

        def ok(_):
            del self.transports[transport_id]

        def fail(err):
            emsg = "Cannot listen on transport endpoint: {log_failure}"
            self.log.error(emsg, log_failure=err)
            raise ApplicationError(u"crossbar.error.cannot_stop", emsg)

        d.addCallbacks(ok, fail)
        return d
Example #16
0
    def session_kill(self,
                     session_id,
                     reason=None,
                     message=None,
                     details=None):
        """
        Forcefully kill a session.

        :param session_id: The WAMP session ID of the session to kill.
        :type session_id: int
        :param reason: A reason URI provided to the killed session.
        :type reason: str or None
        """
        if session_id in self._router._session_id_to_session:
            session = self._router._session_id_to_session[session_id]
            if not is_restricted_session(session):
                session.leave(reason=reason, message=message)
                return
        raise ApplicationError(
            ApplicationError.NO_SUCH_SESSION,
            u'no session with ID {} exists on this router'.format(session_id),
        )
Example #17
0
    def stop_router_realm(self, realm_id, details=None):
        """
        Stop a realm currently running on this router worker.

        When a realm has stopped, no new session will be allowed to attach to the realm.
        Optionally, close all sessions currently attached to the realm.

        :param id: ID of the realm to stop.
        :type id: str

        :param details: Call details.
        :type details: :class:`autobahn.wamp.types.CallDetails`
        """
        self.log.info("{name}.stop_router_realm", name=self.__class__.__name__)

        if realm_id not in self.realms:
            raise ApplicationError("crossbar.error.no_such_object", "No realm with ID '{}'".format(realm_id))

        rlm = self.realms[realm_id]
        realm_name = rlm.config['name']

        # stop the RouterServiceAgent living on the realm
        yield rlm.session.leave()
        self._router_session_factory.remove(rlm.session)
        self.log.info('RouterServiceAgent stopped on realm "{realm_name}"', realm_name=realm_name)

        detached_sessions = self._router_factory.stop_realm(realm_name)

        del self.realms[realm_id]
        del self.realm_to_id[realm_name]

        realm_stopped = {
            'id': realm_id,
            'name': realm_name,
            'detached_sessions': sorted(detached_sessions)
        }

        self.publish('{}.on_realm_stopped'.format(self._uri_prefix), realm_id)
        returnValue(realm_stopped)
Example #18
0
    def get_router_realm_roles(self, realm_id, details=None):
        """
        Get roles currently running on a realm running on this router worker.

        :param realm_id: The ID of the realm to list roles for.
        :type realm_id: str

        :param details: Call details.
        :type details: :class:`autobahn.wamp.types.CallDetails`

        :returns: A list of roles.
        :rtype: list[dict]
        """
        self.log.debug("{name}.get_router_realm_roles({realm_id})",
                       name=self.__class__.__name__,
                       realm_id=realm_id)

        if realm_id not in self.realms:
            raise ApplicationError("crossbar.error.no_such_object",
                                   "No realm with ID '{}'".format(realm_id))

        return self.realms[realm_id].roles.values()
Example #19
0
    def get_router_realm(self, realm_id, details=None):
        """
        Return realm detail information.

        :param realm_id: Realm ID within router worker.
        :type realm_id: str

        :param details: Call details.
        :type details: :class:`autobahn.wamp.types.CallDetails`

        :returns: realm information object
        :rtype: dict
        """
        self.log.debug("{name}.get_router_realm(realm_id={realm_id})",
                       name=self.__class__.__name__,
                       realm_id=realm_id)

        if realm_id not in self.realms:
            raise ApplicationError("crossbar.error.no_such_object",
                                   "No realm with ID '{}'".format(realm_id))

        return self.realms[realm_id].marshal()
Example #20
0
 def authenticate(realm, authid, details):
     self.log.info("WAMP-CRA dynamic authenticator invoked: "
                   "realm='{}', authid='{}', details='{}".format(
                       realm, authid, details))
     try:
         data = yield self.call('com.example.database.get_user', authid)
         if data:
             algorithm, salt, iterations, keylen, derived = data[
                 'password'].split('$')
             returnValue({
                 'secret': derived,
                 'salt': salt,
                 'iterations': int(iterations),
                 'keylen': int(keylen),
                 'role': data['role']
             })
             return
     except ApplicationError:
         pass
     raise ApplicationError(
         'com.example.no_such_user', 'could not authenticate session '
         '- no such user {}'.format(authid))
Example #21
0
    def registration_get(self, registration_id):
        """
        Get registration details.

        :param registration_id: The ID of the registration to retrieve.
        :type registration_id: int

        :returns: The registration details.
        :rtype: dict
        """
        registration = self._router._dealer._registration_map.get_observation_by_id(registration_id)
        if registration and not is_protected_uri(registration.uri):
            registration_details = {
                'id': registration.id,
                'created': registration.created,
                'uri': registration.uri,
                'match': registration.match,
                'invoke': registration.extra.invoke,
            }
            return registration_details
        else:
            raise ApplicationError(ApplicationError.NO_SUCH_REGISTRATION, message="no registration with ID {} exists on this dealer".format(registration_id))
Example #22
0
    async def delete_mrealm_by_name(self,
                                    mrealm_name,
                                    cascade=False,
                                    details=None):
        """
        Delete an existing management realm (by name).

        :param mrealm_name: Name of the management realm to be deleted.
        :type mrealm_name: str

        :param cascade: Automatically unpair (but not delete) any nodes currently paired with and
            unassign (but not delete) any users currently assigned to the management realm to be deleted.
        :type cascade: bool

        :param details: Call details
        :type details: :class:`autobahn.wamp.types.CallDetails`

        :return:
        """
        self.log.info(
            '{klass}.delete_mrealm_by_name(mrealm_name={mrealm_name}, cascade={cascade}, details={details})',
            klass=self.__class__.__name__,
            mrealm_name=mrealm_name,
            cascade=cascade,
            details=details)

        with self.db.begin() as txn:
            mrealm_oid = self.schema.idx_mrealms_by_name[txn, mrealm_name]

        if mrealm_oid:
            deleted = await self.delete_mrealm(mrealm_oid,
                                               cascade=cascade,
                                               details=details)
            return deleted
        else:
            raise ApplicationError(
                'crossbar.error.no_such_object',
                'no management realm with name "{}"'.format(mrealm_name))
Example #23
0
    def set_process_stats_monitoring(self, interval, details=None):
        """
        Enable/disable periodic publication of process statistics.

        :param interval: The monitoring interval in seconds. Set to 0 to disable monitoring.
        :type interval: float
        """
        self.log.debug("{cls}.set_process_stats_monitoring(interval = {interval})",
                       cls=self.__class__.__name__, interval=interval)

        if self._pinfo:

            stats_monitor_set_topic = '{}.on_process_stats_monitoring_set'.format(self._uri_prefix)

            # stop and remove any existing monitor
            if self._pinfo_monitor:
                self._pinfo_monitor.stop()
                self._pinfo_monitor = None

                self.publish(stats_monitor_set_topic, 0, options=PublishOptions(exclude=details.caller))

            # possibly start a new monitor
            if interval > 0:
                stats_topic = '{}.on_process_stats'.format(self._uri_prefix)

                def publish_stats():
                    stats = self._pinfo.get_stats()
                    self._pinfo_monitor_seq += 1
                    stats[u'seq'] = self._pinfo_monitor_seq
                    self.publish(stats_topic, stats)

                self._pinfo_monitor = LoopingCall(publish_stats)
                self._pinfo_monitor.start(interval)

                self.publish(stats_monitor_set_topic, interval, options=PublishOptions(exclude=details.caller))
        else:
            emsg = "Cannot setup process statistics monitor: required packages not installed"
            raise ApplicationError(u"crossbar.error.feature_unavailable", emsg)
Example #24
0
    def _press(self):
        """button pressed handler"""

        self.log.info('Button pressed handler on thread {thread_id}', thread_id=current_thread().ident)

        """ if the button is pressed during the progress is running this Error will be fired"""
        if self._is_pressed:
            raise ApplicationError(u'{}.already-pressed'.format(self._prefix), 'Button is already pressed ')

        self._is_pressed = True
        self.log.info("Pressed")

        """ publish event button_pressed"""
        self.publish(u'{}.button_pressed'.format(self._prefix))

        """wait for a short time"""
        yield sleep(1000 / 1000.)

        self._is_pressed = False
        """ publish event button_released"""
        self.publish(u'{}.button_released'.format(self._prefix))

        self.log.info("released")
Example #25
0
    def session_get(self, session_id, details=None):
        """
        Get details for given session.

        :param session_id: The WAMP session ID to retrieve details for.
        :type session_id: int

        :returns: WAMP session details.
        :rtype: dict or None
        """
        self.log.debug('wamp.session.get("{session_id}")',
                       session_id=session_id)
        if session_id in self._router._session_id_to_session:
            session = self._router._session_id_to_session[session_id]
            if not is_restricted_session(session):
                session_info = session._session_details.marshal()
                session_info[
                    u'transport'] = None if session._transport is None else session._transport._transport_info
                return session_info
        raise ApplicationError(
            ApplicationError.NO_SUCH_SESSION,
            u'no session with ID {} exists on this router'.format(session_id),
        )
Example #26
0
    def get_router_realm_links(self, realm_id, details=None):
        """
        Returns the currently running routing links to remote router realms.

        :param realm_id: The ID of the (local) realm to get links for.
        :type realm_id: str

        :returns: List of router link IDs.
        :rtype: list[str]
        """
        assert type(realm_id) == str
        assert isinstance(details, CallDetails)

        self.log.info(
            'Getting router links for realm {realm_id} {method}',
            realm_id=hlid(realm_id),
            method=hltype(RouterController.get_router_realm_links))

        if realm_id not in self.realms:
            raise ApplicationError("crossbar.error.no_such_object", "No realm with ID '{}'".format(realm_id))

        rlink_manager = self.realms[realm_id].rlink_manager

        return rlink_manager.keys()
Example #27
0
    def get_router_realm_by_name(self, realm_name, details=None):
        """
        Return realm detail information.

        :param realm_name: Realm name.
        :type realm_name: str

        :param details: Call details.
        :type details: :class:`autobahn.wamp.types.CallDetails`

        :returns: realm information object
        :rtype: dict
        """
        self.log.debug(
            '{klass}.get_router_realm_by_name(realm_name="{realm_name}")',
            klass=self.__class__.__name__,
            realm_name=realm_name)

        if realm_name not in self.realm_to_id:
            raise ApplicationError(
                'crossbar.error.no_such_object',
                'No realm with name "{}"'.format(realm_name))

        return self.realms[self.realm_to_id[realm_name]].marshal()
Example #28
0
        def on_event(url, *args, **kwargs):

            headers = Headers({"Content-Type": ["application/json"]})

            body = json.dumps({
                "args": args,
                "kwargs": kwargs
            },
                              sort_keys=True,
                              separators=(',', ':'))
            res = yield self._webtransport.request(method,
                                                   url.encode("utf8"),
                                                   data=body,
                                                   headers=headers)

            if expectedCode:
                if not res.code == expectedCode:
                    raise ApplicationError(
                        "Request returned {}, not the expected {}".format(
                            res.code, expectedCode))

            if debug:
                content = yield self._webtransport.text_content(res)
                log.msg(content)
Example #29
0
    def get_router_transport(self, transport_id, details=None):
        """
        Get transports currently running in this router worker.

        :param details: Call details.
        :type details: :class:`autobahn.wamp.types.CallDetails`

        :returns: List of transports currently running.
        :rtype: list[dict]
        """
        self.log.debug("{name}.get_router_transport",
                       name=self.__class__.__name__)

        if transport_id in self.transports:
            transport = self.transports[transport_id]
            obj = {
                u'id': transport.id,
                u'created': utcstr(transport.created),
                u'config': transport.config,
            }
            return obj
        else:
            raise ApplicationError(u"crossbar.error.no_such_object",
                                   "No transport {}".format(transport_id))
Example #30
0
 def authenticate(realm, authid, details):
     print(
         "WAMP-Anonymous dynamic authenticator invoked: realm='{}', authid='{}'"
         .format(realm, authid))
     pprint(details)
     if re.match(r'tcp4:172\.33\.1[0-2]\..*:.*',
                 details["transport"]["peer"]):
         principal = {
             u'realm': u'dappnode_admin',
             u'role': u'admin',
         }
         return principal
     elif re.match(r'tcp4:172\.33\.1\..*:.*',
                   details["transport"]["peer"]):
         principal = {
             u'realm': u'dappnode_admin',
             u'role': u'core_package',
         }
         return principal
     else:
         raise ApplicationError(
             "no_such_user.authenticate.wamp.dnp.dappnode.eth",
             "could not authenticate session - no such principal {}".
             format(authid))
Example #31
0
    async def unpair_node_by_pubkey(self, pubkey, details=None):
        """

        :param pubkey:

        :param details: Call details
        :type details: :class:`autobahn.wamp.types.CallDetails`

        :return:
        """
        self.log.info(
            '{klass}.unpair_node_by_pubkey(pubkey={pubkey}, details={details})',
            klass=self.__class__.__name__,
            pubkey=pubkey,
            details=details)

        with self.db.begin() as txn:
            node_oid = self.schema.idx_nodes_by_pubkey[txn, pubkey]
        if node_oid:
            unpaired = await self.unpair_node(str(node_oid), details=details)
            return unpaired
        else:
            raise ApplicationError('crossbar.error.no_such_object',
                                   'no node with pubkey {}'.format(pubkey))
Example #32
0
    def sell(self,
             key_id,
             buyer_pubkey,
             amount_paid,
             post_balance,
             signature,
             details=None):
        """

        :param key_id:
        :param buyer_pubkey:
        :param amount_paid:
        :param post_balance:
        :param signature:
        :param details:
        :return:
        """
        if key_id not in self._keys_map:
            raise ApplicationError('crossbar.error.no_such_object',
                                   'no key with ID "{}"'.format(key_id))

        key_series = self._keys_map[key_id]

        encrypted_key = key_series.encrypt_key(key_id, buyer_pubkey)

        self.log.info(
            '{tx_type} key "{key_id}" sold for {amount_earned} [caller={caller}, caller_authid="{caller_authid}", buyer_pubkey="{buyer_pubkey}"]',
            tx_type=hl('XBR SELL  ', color='magenta'),
            key_id=hl(uuid.UUID(bytes=key_id)),
            amount_earned=hl(str(amount_paid) + ' XBR', color='magenta'),
            # paying_channel=hl(binascii.b2a_hex(paying_channel).decode()),
            caller=hl(details.caller),
            caller_authid=hl(details.caller_authid),
            buyer_pubkey=hl(binascii.b2a_hex(buyer_pubkey).decode()))

        return encrypted_key