Пример #1
0
    def _callback_new_block(self, latest_block: Dict):
        """Called once a new block is detected by the alarm task.

        Note:
            This should be called only once per block, otherwise there will be
            duplicated `Block` state changes in the log.

            Therefore this method should be called only once a new block is
            mined with the corresponding block data from the AlarmTask.
        """
        # User facing APIs, which have on-chain side-effects, force polled the
        # blockchain to update the node's state. This force poll is used to
        # provide a consistent view to the user, e.g. a channel open call waits
        # for the transaction to be mined and force polled the event to update
        # the node's state. This pattern introduced a race with the alarm task
        # and the task which served the user request, because the events are
        # returned only once per filter. The lock below is to protect against
        # these races (introduced by the commit
        # 3686b3275ff7c0b669a6d5e2b34109c3bdf1921d)
        with self.event_poll_lock:
            latest_block_number = latest_block["number"]

            # Handle testing with private chains. The block number can be
            # smaller than confirmation_blocks
            confirmed_block_number = max(
                GENESIS_BLOCK_NUMBER,
                latest_block_number -
                self.config["blockchain"]["confirmation_blocks"],
            )
            confirmed_block = self.chain.client.web3.eth.getBlock(
                confirmed_block_number)

            # These state changes will be procesed with a block_number which is
            # /larger/ than the ChainState's block_number.
            for event in self.blockchain_events.poll_blockchain_events(
                    confirmed_block_number):
                on_blockchain_event(self, event)

            # On restart the Raiden node will re-create the filters with the
            # ethereum node. These filters will have the from_block set to the
            # value of the latest Block state change. To avoid missing events
            # the Block state change is dispatched only after all of the events
            # have been processed.
            #
            # This means on some corner cases a few events may be applied
            # twice, this will happen if the node crashed and some events have
            # been processed but the Block state change has not been
            # dispatched.
            state_change = Block(
                block_number=confirmed_block_number,
                gas_limit=confirmed_block["gasLimit"],
                block_hash=BlockHash(bytes(confirmed_block["hash"])),
            )

            # Note: It's important to /not/ block here, because this function
            # can be called from the alarm task greenlet, which should not
            # starve.
            self.handle_and_track_state_change(state_change)
Пример #2
0
    def install_and_query_all_blockchain_filters(
        self,
        token_network_registry_address,
        secret_registry_address,
        from_block=0,
    ):
        token_network_registry = self.chain.token_network_registry(
            token_network_registry_address)
        secret_registry = self.chain.secret_registry(secret_registry_address)
        channels = views.list_all_channelstate(views.state_from_raiden(self), )
        token_networks = views.get_token_network_identifiers(
            views.state_from_raiden(self),
            token_network_registry_address,
        )

        # Install the filters and then poll them and dispatch the events to the WAL
        with self.event_poll_lock:
            self.blockchain_events.add_token_network_registry_listener(
                token_network_registry,
                from_block,
            )
            self.blockchain_events.add_secret_registry_listener(
                secret_registry,
                from_block,
            )

            for token_network in token_networks:
                token_network_proxy = self.chain.token_network(token_network)
                self.blockchain_events.add_token_network_listener(
                    token_network_proxy,
                    from_block,
                )

            for channel_state in channels:
                channel_proxy = self.chain.payment_channel(
                    channel_state.token_network_identifier,
                    channel_state.identifier,
                )
                self.blockchain_events.add_payment_channel_listener(
                    channel_proxy,
                    from_block,
                )

            chain_id = self.chain.network_id
            # We need to query the events at this point in order to obtain an up to
            # date view of the blockchain right before the node starts its transport
            # and starts receiving messages.
            for event in self.blockchain_events.poll_blockchain_events(
                    self.get_block_number(), ):
                on_blockchain_event(
                    self,
                    event,
                    event.event_data['block_number'],
                    chain_id,
                )
Пример #3
0
    def install_and_query_payment_network_filters(self, payment_network_id, from_block=0):
        proxies = get_relevant_proxies(
            self.chain,
            self.address,
            payment_network_id,
        )

        # Install the filters and then poll them and dispatch the events to the WAL
        with self.event_poll_lock:
            self.blockchain_events.add_proxies_listeners(proxies, from_block)
            for event in self.blockchain_events.poll_blockchain_events():
                on_blockchain_event(self, event, event.event_data['block_number'])
Пример #4
0
    def _callback_new_block(self, latest_block: Dict):
        """Called once a new block is detected by the alarm task.

        Note:
            This should be called only once per block, otherwise there will be
            duplicated `Block` state changes in the log.

            Therefore this method should be called only once a new block is
            mined with the corresponding block data from the AlarmTask.
        """
        # User facing APIs, which have on-chain side-effects, force polled the
        # blockchain to update the node's state. This force poll is used to
        # provide a consistent view to the user, e.g. a channel open call waits
        # for the transaction to be mined and force polled the event to update
        # the node's state. This pattern introduced a race with the alarm task
        # and the task which served the user request, because the events are
        # returned only once per filter. The lock below is to protect against
        # these races (introduced by the commit
        # 3686b3275ff7c0b669a6d5e2b34109c3bdf1921d)
        with self.event_poll_lock:
            latest_block_number = latest_block['number']
            confirmation_blocks = self.config['blockchain']['confirmation_blocks']
            confirmed_block_number = latest_block_number - confirmation_blocks
            confirmed_block = self.chain.client.web3.eth.getBlock(confirmed_block_number)

            # handle testing private chains
            confirmed_block_number = max(GENESIS_BLOCK_NUMBER, confirmed_block_number)

            for event in self.blockchain_events.poll_blockchain_events(confirmed_block_number):
                # These state changes will be procesed with a block_number
                # which is /larger/ than the ChainState's block_number.
                on_blockchain_event(self, event)

            # On restart the Raiden node will re-create the filters with the
            # ethereum node. These filters will have the from_block set to the
            # value of the latest Block state change. To avoid missing events
            # the Block state change is dispatched only after all of the events
            # have been processed.
            #
            # This means on some corner cases a few events may be applied
            # twice, this will happen if the node crashed and some events have
            # been processed but the Block state change has not been
            # dispatched.
            state_change = Block(
                block_number=confirmed_block_number,
                gas_limit=confirmed_block['gasLimit'],
                block_hash=bytes(confirmed_block['hash']),
            )
            self.handle_state_change(state_change)
Пример #5
0
    def _callback_new_block(self, latest_block):
        """Called once a new block is detected by the alarm task.

        Note:
            This should be called only once per block, otherwise there will be
            duplicated `Block` state changes in the log.

            Therefore this method should be called only once a new block is
            mined with the appropriate block_number argument from the
            AlarmTask.
        """
        # Raiden relies on blockchain events to update its off-chain state,
        # therefore some APIs /used/ to forcefully poll for events.
        #
        # This was done for APIs which have on-chain side-effects, e.g.
        # openning a channel, where polling the event is required to update
        # off-chain state to providing a consistent view to the caller, e.g.
        # the channel exists after the API call returns.
        #
        # That pattern introduced a race, because the events are returned only
        # once per filter, and this method would be called concurrently by the
        # API and the AlarmTask. The following lock is necessary, to ensure the
        # expected side-effects are properly applied (introduced by the commit
        # 3686b3275ff7c0b669a6d5e2b34109c3bdf1921d)
        latest_block_number = latest_block['number']
        with self.event_poll_lock:
            for event in self.blockchain_events.poll_blockchain_events(
                    latest_block_number):
                # These state changes will be procesed with a block_number
                # which is /larger/ than the ChainState's block_number.
                on_blockchain_event(self, event)

            # On restart the Raiden node will re-create the filters with the
            # ethereum node. These filters will have the from_block set to the
            # value of the latest Block state change. To avoid missing events
            # the Block state change is dispatched only after all of the events
            # have been processed.
            #
            # This means on some corner cases a few events may be applied
            # twice, this will happen if the node crashed and some events have
            # been processed but the Block state change has not been
            # dispatched.
            state_change = Block(
                block_number=latest_block_number,
                gas_limit=latest_block['gasLimit'],
                block_hash=bytes(latest_block['hash']),
            )
            self.handle_state_change(state_change)
Пример #6
0
    def install_and_query_payment_network_filters(
            self,
            token_network_registry_address,
            from_block=0,
    ):
        token_network_registry = self.chain.token_network_registry(token_network_registry_address)

        # Install the filters and then poll them and dispatch the events to the WAL
        with self.event_poll_lock:
            self.blockchain_events.add_token_network_registry_listener(
                token_network_registry,
                from_block,
            )

            for event in self.blockchain_events.poll_blockchain_events():
                on_blockchain_event(self, event, event.event_data['block_number'])
Пример #7
0
    def _callback_new_block(self, latest_block):
        """Called once a new block is detected by the alarm task.

        Note:
            This should be called only once per block, otherwise there will be
            duplicated `Block` state changes in the log.

            Therefore this method should be called only once a new block is
            mined with the corresponding block data from the AlarmTask.
        """
        # User facing APIs, which have on-chain side-effects, force polled the
        # blockchain to update the node's state. This force poll is used to
        # provide a consistent view to the user, e.g. a channel open call waits
        # for the transaction to be mined and force polled the event to update
        # the node's state. This pattern introduced a race with the alarm task
        # and the task which served the user request, because the events are
        # returned only once per filter. The lock below is to protect against
        # these races (introduced by the commit
        # 3686b3275ff7c0b669a6d5e2b34109c3bdf1921d)
        with self.event_poll_lock:
            latest_block_number = latest_block['number']

            for event in self.blockchain_events.poll_blockchain_events(
                    latest_block_number):
                # These state changes will be procesed with a block_number
                # which is /larger/ than the ChainState's block_number.
                on_blockchain_event(self, event)

            # On restart the Raiden node will re-create the filters with the
            # ethereum node. These filters will have the from_block set to the
            # value of the latest Block state change. To avoid missing events
            # the Block state change is dispatched only after all of the events
            # have been processed.
            #
            # This means on some corner cases a few events may be applied
            # twice, this will happen if the node crashed and some events have
            # been processed but the Block state change has not been
            # dispatched.
            state_change = Block(
                block_number=latest_block_number,
                gas_limit=latest_block['gasLimit'],
                block_hash=bytes(latest_block['hash']),
            )
            self.handle_state_change(state_change)
Пример #8
0
    def _callback_new_block(self, current_block_number, chain_id):
        """Called once a new block is detected by the alarm task.

        Note:
            This should be called only once per block, otherwise there will be
            duplicated `Block` state changes in the log.

            Therefore this method should be called only once a new block is
            mined with the appropriate block_number argument from the
            AlarmTask.
        """
        # Raiden relies on blockchain events to update its off-chain state,
        # therefore some APIs /used/ to forcefully poll for events.
        #
        # This was done for APIs which have on-chain side-effects, e.g.
        # openning a channel, where polling the event is required to update
        # off-chain state to providing a consistent view to the caller, e.g.
        # the channel exists after the API call returns.
        #
        # That pattern introduced a race, because the events are returned only
        # once per filter, and this method would be called concurrently by the
        # API and the AlarmTask. The following lock is necessary, to ensure the
        # expected side-effects are properly applied (introduced by the commit
        # 3686b3275ff7c0b669a6d5e2b34109c3bdf1921d)
        with self.event_poll_lock:
            for event in self.blockchain_events.poll_blockchain_events(current_block_number):
                # These state changes will be procesed with a block_number
                # which is /larger/ than the ChainState's block_number.
                on_blockchain_event(self, event, current_block_number, chain_id)

            # On restart the Raiden node will re-create the filters with the
            # ethereum node. These filters will have the from_block set to the
            # value of the latest Block state change. To avoid missing events
            # the Block state change is dispatched only after all of the events
            # have been processed.
            #
            # This means on some corner cases a few events may be applied
            # twice, this will happen if the node crashed and some events have
            # been processed but the Block state change has not been
            # dispatched.
            state_change = Block(current_block_number)
            self.handle_state_change(state_change, current_block_number)
Пример #9
0
 def poll_blockchain_events(self, current_block=None):  # pylint: disable=unused-argument
     with self.event_poll_lock:
         for event in self.blockchain_events.poll_blockchain_events():
             on_blockchain_event(self, event)