Example #1
0
    def start(self, known_ids=None):
        """Subscribes to state delta events, and then waits to receive deltas.
        Sends any events received to delta handlers.
        """
        if not known_ids:
            known_ids = [NULL_BLOCK_ID]

        self._stream.wait_for_ready()
        LOGGER.debug('Subscribing to state delta events')

        block_sub = EventSubscription(event_type='sawtooth/block-commit')
        delta_sub = EventSubscription(
            event_type='sawtooth/state-delta',
            filters=[
                EventFilter(key='address',
                            match_string='^{}.*'.format(NAMESPACE),
                            filter_type=EventFilter.REGEX_ANY)
            ])

        request = ClientEventsSubscribeRequest(
            last_known_block_ids=known_ids,
            subscriptions=[block_sub, delta_sub])
        response_future = self._stream.send(
            Message.CLIENT_EVENTS_SUBSCRIBE_REQUEST,
            request.SerializeToString())
        response = ClientEventsSubscribeResponse()
        response.ParseFromString(response_future.result().content)

        # Forked all the way back to genesis, restart with no known_ids
        if (response.status == ClientEventsSubscribeResponse.UNKNOWN_BLOCK
                and known_ids):
            return self.start()

        if response.status != ClientEventsSubscribeResponse.OK:
            raise RuntimeError('Subscription failed with status: {}'.format(
                ClientEventsSubscribeResponse.Status.Name(response.status)))

        self._is_active = True

        LOGGER.debug('Successfully subscribed to state delta events')
        while self._is_active:
            message_future = self._stream.receive()

            event_list = EventList()
            event_list.ParseFromString(message_future.result().content)
            for handler in self._event_handlers:
                handler(event_list.events)
Example #2
0
    async def subscribe_events(self, web_sock, last_known_block_id=None):
        # Setup a connection to the validator
        LOGGER.debug(f"Subscription started")

        request = ClientEventsSubscribeRequest(
            subscriptions=self._make_subscriptions(),
            last_known_block_ids=[last_known_block_id]
            if last_known_block_id else []).SerializeToString()

        # Construct the message wrapper
        correlation_id = generate_random_key(
        )  # This must be unique for all in-process requests
        msg = Message(correlation_id=correlation_id,
                      message_type=Message.CLIENT_EVENTS_SUBSCRIBE_REQUEST,
                      content=request)

        # Send the request
        LOGGER.debug(f"Sending subscription request.")

        await self._loop.run_in_executor(
            None,
            lambda: self._socket.send_multipart([msg.SerializeToString()]))
        LOGGER.debug(f"Subscription request is sent")

        msg = await self._event_queue[Message.CLIENT_EVENTS_SUBSCRIBE_RESPONSE
                                      ].get()

        LOGGER.info(f"message type {msg.message_type}")

        # Validate the response type
        if msg.message_type != Message.CLIENT_EVENTS_SUBSCRIBE_RESPONSE:
            LOGGER.error(f"Skip unexpected message type")
            return

        # Parse the response
        response = ClientEventsSubscribeResponse()
        response.ParseFromString(msg.content)

        # Validate the response status
        if response.status != ClientEventsSubscribeResponse.OK:
            if response.status == ClientEventsSubscribeResponse.UNKNOWN_BLOCK:
                raise SocketException(
                    web_sock, Status.UNKNOWN_BLOCK,
                    f"Uknown block in: {last_known_block_id}")
            raise SocketException(
                web_sock, 0, "Subscription failed: Couldn't send multipart")
        LOGGER.debug(f"Successfully subscribed")
Example #3
0
def set_up_zmq_subscription():
    """
    This sends a subscription request to ZMQ.
    See: https://sawtooth.hyperledger.org/docs/core/
    releases/latest/app_developers_guide/zmq_event_subscription.html
    """
    subscription = EventSubscription(
        event_type="sawtooth/state-delta",
        filters=[
            EventFilter(
                key="address",
                match_string="b89bcb.*",
                filter_type=EventFilter.REGEX_ANY)
        ])

    request = ClientEventsSubscribeRequest(
        subscriptions=[subscription]
    ).SerializeToString()

    correlation_id = "123"  # This must be unique for all in-process requests
    msg = Message(
        correlation_id=correlation_id,
        message_type=Message.MessageType.CLIENT_EVENTS_SUBSCRIBE_REQUEST,
        content=request
    )

    socket.send_multipart([msg.SerializeToString()])

    resp = socket.recv_multipart()[-1]

    msg = Message()
    msg.ParseFromString(resp)

    if msg.message_type != \
       Message.MessageType.CLIENT_EVENTS_SUBSCRIBE_RESPONSE:
        print("Unexpected message type")
        exit(1)

    response = ClientEventsSubscribeResponse()
    response.ParseFromString(msg.content)

    if response.status != ClientEventsSubscribeResponse.OK:
        print("Subscription failed: {}".format(response.response_message))
        exit(1)

    LOGGER.debug("Setting up ZMQ subscription successful")
Example #4
0
    def subscribe_to_event(self):

        LOGGER.info("Subscribing to event {}".format(self._event))

        done_sub = EventSubscription(event_type=self._event)
        request = ClientEventsSubscribeRequest(subscriptions=[done_sub])

        response_future = self._stream.send(
            Message.CLIENT_EVENTS_SUBSCRIBE_REQUEST,
            request.SerializeToString())

        sub_response = ClientEventsSubscribeResponse()
        sub_response.ParseFromString(response_future.result().content)

        if sub_response.status == ClientEventsSubscribeResponse.OK:
            self._is_active = True
            LOGGER.info('Subscription with response {}'.format(
                sub_response.status))
        else:
            LOGGER.error('Could not Subscribe to event')
            raise SubscriberError()
Example #5
0
    def listen_to_event(self):
        self._stream.wait_for_ready()
        # Step 1: Construct a Subscription
        block_sub = EventSubscription(event_type='sawtooth/block-commit')

        # Step 2: Submit the Event Subscription
        request = ClientEventsSubscribeRequest(subscriptions=[block_sub])

        response_future = self._stream.send(
            Message.CLIENT_EVENTS_SUBSCRIBE_REQUEST,
            request.SerializeToString())

        response = ClientEventsSubscribeResponse()
        response.ParseFromString(response_future.result().content)

        # Listen for events in an infinite loop
        LOGGER.warning("Listening to events.")
        while True:
            msg = self._stream.receive()
            event_list = EventList()
            event_list.ParseFromString(msg.result().content)
            for handler in self._event_handlers:
                handler(event_list.events)
Example #6
0
async def subscribe(request):
    ws = request.ws
    if ws is None:
        raise ClientException(
            message='Subscription available only through websocket')

    msg_id = request.msg.data['id']

    request.params = request.params or {}
    try:
        event_type = request.params['event_type']
    except KeyError as e:
        raise RpcInvalidParamsError(message='Missed event_type')

    try:
        evt_tr = EVENT_HANDLERS[event_type]
    except KeyError:
        raise ClientException(message=f'Event "{event_type}" not defined')

    async with event_lock:
        subsevt = request.rpc._subsevt.setdefault(ws, {})
        if event_type in subsevt:
            raise ClientException(
                message=f'Already subscribed to event "{event_type}"')

        router = ws.stream.router

        event_types = set(subsevt.keys())
        event_types.add(event_type)

        LOGGER.debug(f'Events to re-subsribe: {event_types}')

        validated_data = evt_tr.validate(msg_id, request.params)
        from_block = validated_data.get('from_block')
        if not from_block:
            from_block = (await router.list_blocks(limit=1))['head']

        req_msg = evt_tr.prepare_subscribe_message(event_types, from_block)

        LOGGER.debug(f'Request message: {req_msg}')

        msg = await ws.stream.send(
            message_type=Message.CLIENT_EVENTS_SUBSCRIBE_REQUEST,
            message_content=req_msg.SerializeToString(),
            timeout=ZMQ_CONNECTION_TIMEOUT)

        LOGGER.debug(f'Message type: {msg.message_type}')

        # Validate the response type
        if msg.message_type != Message.CLIENT_EVENTS_SUBSCRIBE_RESPONSE:
            raise ClientException(
                message=f'Unexpected message type {msg.message_type}')

        # Parse the response
        response = ClientEventsSubscribeResponse()
        response.ParseFromString(msg.content)

        # Validate the response status
        if response.status != ClientEventsSubscribeResponse.OK:
            if response.status == ClientEventsSubscribeResponse.UNKNOWN_BLOCK:
                raise ClientException(message=f'Unknown block "{from_block}"')
            raise ClientException(message='Subscription failed: Couldn\'t '
                                  'send multipart')

        if ws not in request.rpc._evthashes:
            request.rpc._evthashes[ws] = set()

        LOGGER.debug(f'Create cosumer task for {ws}')
        request.rpc.loop.create_task(_consumer(request))

        if event_type == 'batch':
            LOGGER.debug(f'Create producer task for {ws}')
            request.rpc.loop.create_task(_producer(request))

        subsevt[event_type] = {
            'msg_id': msg_id,
            'validated_data': validated_data,
        }

    return 'SUBSCRIBED'
Example #7
0
    def subscribe(self, event_name: str, is_write_to_file=False, file_name='certificate.pem'):
        subscription = EventSubscription(event_type="ca_1/{}".format(event_name))

        # Setup a connection to the validator
        ctx = zmq.Context()
        socket = ctx.socket(zmq.DEALER)
        socket.connect('tcp://127.0.0.1:4004')

        # Construct the request
        request = ClientEventsSubscribeRequest(
            subscriptions=[subscription]).SerializeToString()

        # Construct the message wrapper
        correlation_id = "123"  # This must be unique for all in-process requests
        msg = Message(
            correlation_id=correlation_id,
            message_type=Message.CLIENT_EVENTS_SUBSCRIBE_REQUEST,
            content=request)

        # Send the request
        socket.send_multipart([msg.SerializeToString()])

        # Receive the response
        resp = socket.recv_multipart()[-1]

        # Parse the message wrapper
        msg = Message()
        msg.ParseFromString(resp)

        # Validate the response type
        if msg.message_type != Message.CLIENT_EVENTS_SUBSCRIBE_RESPONSE:
            print("Unexpected message type")
            return

        # Parse the response
        response = ClientEventsSubscribeResponse()
        response.ParseFromString(msg.content)

        # Validate the response status
        if response.status != ClientEventsSubscribeResponse.OK:
            print("Subscription failed: {}".format(response.response_message))
            return

        resp = socket.recv_multipart()[-1]

        # Parse the message wrapper
        msg = Message()
        msg.ParseFromString(resp)

        # Validate the response type
        if msg.message_type != Message.CLIENT_EVENTS:
            print("Unexpected message type")
            return

        # Parse the response
        events = EventList()
        events.ParseFromString(msg.content)

        for event in events.events:
            if event.data is not None:
                if is_write_to_file:
                    write_to_file(file_name, event.data)
                else:
                    print(event.data)

        # Construct the request
        request = ClientEventsUnsubscribeRequest().SerializeToString()

        # Construct the message wrapper
        correlation_id = "124"  # This must be unique for all in-process requests
        msg = Message(
            correlation_id=correlation_id,
            message_type=Message.CLIENT_EVENTS_UNSUBSCRIBE_REQUEST,
            content=request)

        # Send the request
        socket.send_multipart([msg.SerializeToString()])

        # Receive the response
        resp = socket.recv_multipart()[-1]

        # Parse the message wrapper
        msg = Message()
        msg.ParseFromString(resp)

        # Validate the response type
        if msg.message_type != Message.CLIENT_EVENTS_UNSUBSCRIBE_RESPONSE:
            print("Unexpected message type")

        # Parse the response
        response = ClientEventsUnsubscribeResponse()
        response.ParseFromString(msg.content)

        # Validate the response status
        if response.status != ClientEventsUnsubscribeResponse.OK:
            print("Unsubscription failed: {}".format(response.response_message))

        # Close the connection to the validator
        socket.close()
Example #8
0
def subscribe_event():
    """
     A custom management command to store block information of each block data by event subscription.
     this command is calling from docker-compose file
    """
    logger.info("event function start..")
    # Setup a connection to the validator
    ctx = zmq.Context()
    socket = ctx.socket(zmq.DEALER)
    socket.connect(validator_url)

    # -------------------------------#
    # Submit the Event Subscription  #
    # -------------------------------#

    # subscribe both both "block commit" and "state-delta" event
    block_sub = EventSubscription(event_type='sawtooth/block-commit')
    delta_sub = EventSubscription(
        event_type='sawtooth/state-delta',
        filters=[
            EventFilter(key='address',
                        match_string='^{}.*'.format(NAMESPACE),
                        filter_type=EventFilter.REGEX_ANY)
        ])

    # Construct the request
    request = ClientEventsSubscribeRequest(
        subscriptions=[block_sub, delta_sub]).SerializeToString()

    # Construct the message wrapper
    correlation_id = "123"  # This must be unique for all in-process requests
    msg = Message(correlation_id=correlation_id,
                  message_type=Message.CLIENT_EVENTS_SUBSCRIBE_REQUEST,
                  content=request)

    # Send the request
    socket.send_multipart([msg.SerializeToString()])

    #
    # -------------------------------#
    #     Receive the response       #
    # -------------------------------#

    resp = socket.recv_multipart()[-1]

    # Parse the message wrapper
    msg = Message()
    msg.ParseFromString(resp)

    # Validate the response type
    if msg.message_type != Message.CLIENT_EVENTS_SUBSCRIBE_RESPONSE:
        logger.error("Unexpected message type")
        return

    # Parse the response
    response = ClientEventsSubscribeResponse()
    response.ParseFromString(msg.content)

    # Validate the response status
    if response.status != ClientEventsSubscribeResponse.OK:
        return

    while True:
        resp = socket.recv_multipart()[-1]

        # Parse the message wrapper
        msg = Message()
        msg.ParseFromString(resp)

        # Validate the response type
        if msg.message_type != Message.CLIENT_EVENTS:
            return

        # Parse the response
        events = EventList()
        events.ParseFromString(msg.content)
        block_info = {"address": []}
        event_data = MessageToDict(events)
        events_list = event_data["events"]
        for event in events_list:
            attributes = event["attributes"]

            for attr in attributes:
                key = attr["key"]
                value = attr["value"]
                if key == 'address':
                    block_info["address"].append(value)
                else:
                    block_info[key] = value

        address_list = block_info["address"]
        for address in address_list:
            BlockInfo.objects.create(
                block_num=block_info["block_num"],
                block_id=block_info["block_id"],
                state_root_hash=block_info["state_root_hash"],
                previous_block_id=block_info["previous_block_id"],
                address=address,
            )
            logger.info("blockinfo subscription created..")