示例#1
0
    def _initialize_messages_queues(self, chain_state: ChainState):
        """ Push the queues to the transport and populate
        targets_to_identifiers_to_statuses.
        """
        events_queues = views.get_all_messagequeues(chain_state)

        for queue_identifier, event_queue in events_queues.items():
            self.start_health_check_for(queue_identifier.recipient)

            for event in event_queue:
                is_initiator = (
                    type(event) == SendLockedTransfer and
                    event.transfer.initiator == self.address
                )

                if is_initiator:
                    self._register_payment_status(
                        target=event.transfer.target,
                        identifier=event.transfer.payment_identifier,
                        balance_proof=event.transfer.balance_proof,
                    )

                message = message_from_sendevent(event, self.address)
                self.sign(message)
                self.transport.send_async(queue_identifier, message)
示例#2
0
    def _initialize_messages_queues(self, chain_state):
        """ Push the queues to the transport and populate
        targets_to_identifiers_to_statuses.
        """
        events_queues = views.get_all_messagequeues(chain_state)

        for queue_identifier, event_queue in events_queues.items():
            self.start_health_check_for(queue_identifier.recipient)

            for event in event_queue:
                is_initiator = (
                    type(event) == SendLockedTransfer and
                    event.transfer.initiator == self.address
                )

                if type(event) == SendDirectTransfer:
                    self._register_payment_status(
                        target=event.recipient,
                        identifier=event.payment_identifier,
                        payment_type=PaymentType.DIRECT,
                        balance_proof=event.balance_proof,
                    )
                elif is_initiator:
                    self._register_payment_status(
                        target=event.transfer.target,
                        identifier=event.transfer.payment_identifier,
                        payment_type=PaymentType.MEDIATED,
                        balance_proof=event.transfer.balance_proof,
                    )

                message = message_from_sendevent(event, self.address)
                self.sign(message)
                self.transport.send_async(queue_identifier, message)
示例#3
0
    def start(
        self,
        raiden: RaidenService,
        queueids_to_queues: typing.List[SendMessageEvent],
    ):
        self.raiden = raiden
        self.queueids_to_queues = dict()

        # server.stop() clears the handle. Since this may be a restart the
        # handle must always be set
        self.server.set_handle(self._receive)

        for (recipient, queue_name), queue in queueids_to_queues.items():
            encoded_queue = list()

            for sendevent in queue:
                message = message_from_sendevent(sendevent, raiden.address)
                raiden.sign(message)
                encoded = message.encode()

                encoded_queue.append((encoded, sendevent.message_identifier))

            self.init_queue_for(recipient, queue_name, encoded_queue)

        self.server.start()
示例#4
0
    def cross_handle_recieved_locked_transfer(self, transfer, cross_id):
        self.start_health_check_for(transfer.initiator)
        state_change = target_init(transfer)

        block_number = self.get_block_number()

        event_list = self.wal.log_and_dispatch(state_change, block_number)

        for event in event_list:
            log.debug('RAIDEN EVENT',
                      node=pex(self.address),
                      raiden_event=event)

            if type(event) == SendSecretRequest:
                secret_request_message = message_from_sendevent(
                    event, self.address)
                self.sign(secret_request_message)

                cross_secret_request_message = CrossSecretRequest(
                    secret_request_message, cross_id)
                self.sign(cross_secret_request_message)

                self.transport.send_async(
                    event.recipient,
                    event.queue_name,
                    cross_secret_request_message,
                )
                continue
            on_raiden_event(self, event)

        return event_list
示例#5
0
    def _initialize_messages_queues(self, chain_state: ChainState):
        """Initialize all the message queues with the transport.

        Note:
            All messages from the state queues must be pushed to the transport
            before it's started. This is necessary to avoid a race where the
            transport processes network messages too quickly, queueing new
            messages before any of the previous messages, resulting in new
            messages being out-of-order.

            The Alarm task must be started before this method is called,
            otherwise queues for channel closed while the node was offline
            won't be properly cleared. It is not bad but it is suboptimal.
        """
        assert not self.transport, f"Transport is running. node:{self!r}"
        assert self.alarm.is_primed(), f"AlarmTask not primed. node:{self!r}"

        events_queues = views.get_all_messagequeues(chain_state)

        for queue_identifier, event_queue in events_queues.items():
            self.start_health_check_for(queue_identifier.recipient)

            for event in event_queue:
                message = message_from_sendevent(event)
                self.sign(message)
                self.transport.send_async(queue_identifier, message)
示例#6
0
    def start(
            self,
            raiden: RaidenService,
            queueids_to_queues: typing.List[SendMessageEvent],
    ):
        self.raiden = raiden
        self.queueids_to_queues = dict()

        # server.stop() clears the handle. Since this may be a restart the
        # handle must always be set
        self.server.set_handle(self._receive)

        for (recipient, queue_name), queue in queueids_to_queues.items():
            encoded_queue = list()

            for sendevent in queue:
                message = message_from_sendevent(sendevent, raiden.address)
                raiden.sign(message)
                encoded = message.encode()

                encoded_queue.append((encoded, sendevent.message_identifier))

            self.init_queue_for(recipient, queue_name, encoded_queue)

        self.server.start()
示例#7
0
 def handle_send_lockedtransfer(raiden: "RaidenService",
                                send_locked_transfer: SendLockedTransfer):
     mediated_transfer_message = message_from_sendevent(
         send_locked_transfer)
     raiden.sign(mediated_transfer_message)
     raiden.transport.send_async(send_locked_transfer.queue_identifier,
                                 mediated_transfer_message)
示例#8
0
    def handle_cross_state_change(self,
                                  state_change,
                                  cross_id,
                                  secret,
                                  btc_amount,
                                  block_number=None):
        if block_number is None:
            block_number = self.get_block_number()

        event_list = self.wal.log_and_dispatch(state_change, block_number)

        row = self.wal.storage.get_lnd(1)
        macaroon = row[4]
        lnd_url = "https://{}/v1/invoices".format(self.config['lnd_address'])
        lnd_headers = {'Grpc-Metadata-macaroon': macaroon}
        lnd_r = base64.b64encode(secret)
        lnd_data = {
            'value': btc_amount,
            'r_preimage': lnd_r.decode('utf-8'),
            'type': "CROSS_CHAIN_INVOICE"
        }

        res = requests.post(lnd_url,
                            headers=lnd_headers,
                            data=json.dumps(lnd_data),
                            verify=False)

        res_json = res.json()
        lnd_r_hash = res_json['r_hash']
        lnd_payment_request = res_json['payment_request']
        print('send invoice succ, lnd_r_hash:', lnd_r_hash)

        for event in event_list:
            log.debug('RAIDEN EVENT',
                      node=pex(self.address),
                      raiden_event=event)

            if type(event) == SendLockedTransfer:
                locked_transfer_message = message_from_sendevent(
                    event, self.address)
                self.sign(locked_transfer_message)
                self.wal.storage.change_crosstransaction_r(
                    cross_id,
                    encode_hex(locked_transfer_message.lock.secrethash),
                    lnd_r_hash)
                tmp_r_hash = base64.b64decode(lnd_r_hash)
                raiden_r_hash = locked_transfer_message.lock.secrethash
                hex_r_hash = encode_hex(tmp_r_hash)
                lnd_string = bytes(lnd_payment_request, "utf-8")
                cross_transfer_message = CrossLockedTransfer(
                    locked_transfer_message, cross_id, lnd_string)
                self.sign(cross_transfer_message)
                self.transport.send_async(cross_transfer_message.recipient,
                                          bytes("456", 'utf-8'),
                                          cross_transfer_message)
                print('corss_message send ok')
                continue

            on_raiden_event(self, event)
示例#9
0
 def handle_send_refundtransfer(
     raiden: "RaidenService", refund_transfer_event: SendRefundTransfer
 ):
     refund_transfer_message = message_from_sendevent(refund_transfer_event)
     raiden.sign(refund_transfer_message)
     raiden.transport.send_async(
         refund_transfer_event.queue_identifier, refund_transfer_message
     )
示例#10
0
    def handle_send_secretrequest(
        raiden: "RaidenService", secret_request_event: SendSecretRequest
    ):
        if reveal_secret_with_resolver(raiden, secret_request_event):
            return

        secret_request_message = message_from_sendevent(secret_request_event)
        raiden.sign(secret_request_message)
        raiden.transport.send_async(secret_request_event.queue_identifier, secret_request_message)
示例#11
0
def handle_send_crosstransaction(
        raiden: RaidenService,
        send_crosstransaction_event: SendCrosstransaction):
    crosstransaction_message = message_from_sendevent(
        send_crosstransaction_event, raiden.address)
    raiden.sign(crosstransaction_message)
    raiden.transport.send_async(send_crosstransaction_event.recipient,
                                send_crosstransaction_event.queue_name,
                                crosstransaction_message)
示例#12
0
 def handle_send_balanceproof(
     raiden: 'RaidenService',
     balance_proof_event: SendBalanceProof,
 ):
     unlock_message = message_from_sendevent(balance_proof_event)
     raiden.sign(unlock_message)
     raiden.transport.send_async(
         balance_proof_event.queue_identifier,
         unlock_message,
     )
示例#13
0
 def handle_send_secretreveal(
     raiden: 'RaidenService',
     reveal_secret_event: SendSecretReveal,
 ):
     reveal_secret_message = message_from_sendevent(reveal_secret_event)
     raiden.sign(reveal_secret_message)
     raiden.transport.send_async(
         reveal_secret_event.queue_identifier,
         reveal_secret_message,
     )
示例#14
0
 def handle_send_lockexpired(
     raiden: 'RaidenService',
     send_lock_expired: SendLockExpired,
 ):
     lock_expired_message = message_from_sendevent(send_lock_expired)
     raiden.sign(lock_expired_message)
     raiden.transport.send_async(
         send_lock_expired.queue_identifier,
         lock_expired_message,
     )
def handle_send_balanceproof(
        raiden: RaidenService,
        balance_proof_event: SendBalanceProof,
):
    secret_message = message_from_sendevent(balance_proof_event, raiden.address)
    raiden.sign(secret_message)
    raiden.transport.send_async(
        balance_proof_event.queue_identifier,
        secret_message,
    )
def handle_send_secretrequest(
        raiden: RaidenService,
        secret_request_event: SendSecretRequest,
):
    secret_request_message = message_from_sendevent(secret_request_event, raiden.address)
    raiden.sign(secret_request_message)
    raiden.transport.send_async(
        secret_request_event.queue_identifier,
        secret_request_message,
    )
示例#17
0
def handle_send_processed(
    raiden: RaidenService,
    processed_event: SendProcessed,
):
    processed_message = message_from_sendevent(processed_event, raiden.address)
    raiden.sign(processed_message)
    raiden.transport.send_async(
        processed_event.queue_identifier,
        processed_message,
    )
def handle_send_revealsecret(
        raiden: RaidenService,
        reveal_secret_event: SendRevealSecret,
):
    reveal_secret_message = message_from_sendevent(reveal_secret_event, raiden.address)
    raiden.sign(reveal_secret_message)
    raiden.transport.send_async(
        reveal_secret_event.queue_identifier,
        reveal_secret_message,
    )
def handle_send_directtransfer(
        raiden: RaidenService,
        send_direct_transfer: SendDirectTransfer,
):
    direct_transfer_message = message_from_sendevent(send_direct_transfer, raiden.address)
    raiden.sign(direct_transfer_message)
    raiden.transport.send_async(
        send_direct_transfer.queue_identifier,
        direct_transfer_message,
    )
示例#20
0
 def handle_send_refundtransfer(
         self,
         raiden: RaidenService,
         refund_transfer_event: SendRefundTransfer,
 ):
     refund_transfer_message = message_from_sendevent(refund_transfer_event, raiden.address)
     raiden.sign(refund_transfer_message)
     raiden.transport.send_async(
         refund_transfer_event.queue_identifier,
         refund_transfer_message,
     )
示例#21
0
 def handle_send_balanceproof(
         self,
         raiden: RaidenService,
         balance_proof_event: SendBalanceProof,
 ):
     secret_message = message_from_sendevent(balance_proof_event, raiden.address)
     raiden.sign(secret_message)
     raiden.transport.send_async(
         balance_proof_event.queue_identifier,
         secret_message,
     )
示例#22
0
 def handle_send_secretrequest(
         self,
         raiden: RaidenService,
         secret_request_event: SendSecretRequest,
 ):
     secret_request_message = message_from_sendevent(secret_request_event, raiden.address)
     raiden.sign(secret_request_message)
     raiden.transport.send_async(
         secret_request_event.queue_identifier,
         secret_request_message,
     )
示例#23
0
def handle_send_processed(
    raiden: 'RaidenService',
    processed_event: SendProcessed,
):
    processed_message = message_from_sendevent(processed_event, raiden.address)
    raiden.sign(processed_message)
    raiden.protocol.send_async(
        processed_event.recipient,
        processed_event.queue_name,
        processed_message,
    )
示例#24
0
def handle_send_directtransfer(
        raiden: RaidenService,
        send_direct_transfer: SendDirectTransfer,
):
    direct_transfer_message = message_from_sendevent(send_direct_transfer, raiden.address)
    raiden.sign(direct_transfer_message)
    raiden.transport.send_async(
        send_direct_transfer.recipient,
        send_direct_transfer.queue_name,
        direct_transfer_message,
    )
示例#25
0
 def handle_send_refundtransfer(
         self,
         raiden: RaidenService,
         refund_transfer_event: SendRefundTransfer,
 ):
     refund_transfer_message = message_from_sendevent(refund_transfer_event, raiden.address)
     raiden.sign(refund_transfer_message)
     raiden.transport.send_async(
         refund_transfer_event.queue_identifier,
         refund_transfer_message,
     )
示例#26
0
 def handle_send_lockedtransfer(
         self,
         raiden: RaidenService,
         send_locked_transfer: SendLockedTransfer,
 ):
     mediated_transfer_message = message_from_sendevent(send_locked_transfer, raiden.address)
     raiden.sign(mediated_transfer_message)
     raiden.transport.send_async(
         send_locked_transfer.queue_identifier,
         mediated_transfer_message,
     )
示例#27
0
def handle_send_revealsecret(
        raiden: RaidenService,
        reveal_secret_event: SendRevealSecret,
):
    reveal_secret_message = message_from_sendevent(reveal_secret_event, raiden.address)
    raiden.sign(reveal_secret_message)
    raiden.transport.send_async(
        reveal_secret_event.recipient,
        reveal_secret_event.queue_name,
        reveal_secret_message,
    )
示例#28
0
 def handle_send_lockexpired(
         self,
         raiden: RaidenService,
         send_lock_expired: SendLockExpired,
 ):
     lock_expired_message = message_from_sendevent(send_lock_expired, raiden.address)
     raiden.sign(lock_expired_message)
     raiden.transport.send_async(
         send_lock_expired.queue_identifier,
         lock_expired_message,
     )
示例#29
0
    def _initialize_messages_queues(self, chain_state: ChainState):
        """ Push the message queues to the transport. """
        events_queues = views.get_all_messagequeues(chain_state)

        for queue_identifier, event_queue in events_queues.items():
            self.start_health_check_for(queue_identifier.recipient)

            for event in event_queue:
                message = message_from_sendevent(event, self.address)
                self.sign(message)
                self.transport.send_async(queue_identifier, message)
示例#30
0
 def handle_send_secretreveal(
         self,
         raiden: RaidenService,
         reveal_secret_event: SendSecretReveal,
 ):
     reveal_secret_message = message_from_sendevent(reveal_secret_event, raiden.address)
     raiden.sign(reveal_secret_message)
     raiden.transport.send_async(
         reveal_secret_event.queue_identifier,
         reveal_secret_message,
     )
示例#31
0
 def handle_send_lockedtransfer(
         self,
         raiden: RaidenService,
         send_locked_transfer: SendLockedTransfer,
 ):
     mediated_transfer_message = message_from_sendevent(send_locked_transfer, raiden.address)
     raiden.sign(mediated_transfer_message)
     raiden.transport.send_async(
         send_locked_transfer.queue_identifier,
         mediated_transfer_message,
     )
示例#32
0
 def handle_send_processed(
         self,
         raiden: RaidenService,
         processed_event: SendProcessed,
 ):
     processed_message = message_from_sendevent(processed_event, raiden.address)
     raiden.sign(processed_message)
     raiden.transport.send_async(
         processed_event.queue_identifier,
         processed_message,
     )
示例#33
0
def handle_send_directtransfer(
    raiden: 'RaidenService',
    send_direct_transfer: SendDirectTransfer,
):
    direct_transfer_message = message_from_sendevent(send_direct_transfer,
                                                     raiden.address)
    raiden.sign(direct_transfer_message)
    raiden.protocol.send_async(
        send_direct_transfer.recipient,
        send_direct_transfer.queue_name,
        direct_transfer_message,
    )
示例#34
0
def handle_send_balanceproof(
    raiden: 'RaidenService',
    balance_proof_event: SendBalanceProof,
):
    secret_message = message_from_sendevent(balance_proof_event,
                                            raiden.address)
    raiden.sign(secret_message)
    raiden.protocol.send_async(
        balance_proof_event.recipient,
        balance_proof_event.queue_name,
        secret_message,
    )
示例#35
0
def handle_send_revealsecret(
    raiden: 'RaidenService',
    reveal_secret_event: SendRevealSecret,
):
    reveal_secret_message = message_from_sendevent(reveal_secret_event,
                                                   raiden.address)
    raiden.sign(reveal_secret_message)
    raiden.protocol.send_async(
        reveal_secret_event.recipient,
        reveal_secret_event.queue_name,
        reveal_secret_message,
    )
示例#36
0
def handle_send_refundtransfer(
    raiden: 'RaidenService',
    refund_transfer_event: SendRefundTransfer,
):
    refund_transfer_message = message_from_sendevent(refund_transfer_event,
                                                     raiden.address)
    raiden.sign(refund_transfer_message)
    raiden.protocol.send_async(
        refund_transfer_event.recipient,
        refund_transfer_event.queue_name,
        refund_transfer_message,
    )
示例#37
0
def handle_send_lockedtransfer(
    raiden: 'RaidenService',
    send_locked_transfer: SendLockedTransfer,
):
    mediated_transfer_message = message_from_sendevent(send_locked_transfer,
                                                       raiden.address)
    raiden.sign(mediated_transfer_message)
    raiden.protocol.send_async(
        mediated_transfer_message.recipient,
        send_locked_transfer.queue_name,
        mediated_transfer_message,
    )
示例#38
0
def handle_send_secretrequest(
    raiden: 'RaidenService',
    secret_request_event: SendSecretRequest,
):
    secret_request_message = message_from_sendevent(secret_request_event,
                                                    raiden.address)
    raiden.sign(secret_request_message)
    raiden.protocol.send_async(
        secret_request_event.recipient,
        secret_request_event.queue_name,
        secret_request_message,
    )
def test_regression_onchain_secret_reveal_must_update_channel_state():
    """ If a secret is learned off-chain and then on-chain, the state of the
    lock must be updated in the channel.
    """
    pseudo_random_generator = random.Random()

    setup = factories.make_transfers_pair(2, block_number=10)

    mediator_state = MediatorTransferState(
        secrethash=UNIT_SECRETHASH,
        routes=setup.channels.get_routes(),
    )
    mediator_state.transfers_pair = setup.transfers_pair

    secret = UNIT_SECRET
    secrethash = UNIT_SECRETHASH
    payer_channel = mediator.get_payer_channel(setup.channel_map,
                                               setup.transfers_pair[0])
    payee_channel = mediator.get_payee_channel(setup.channel_map,
                                               setup.transfers_pair[0])
    lock = payer_channel.partner_state.secrethashes_to_lockedlocks[secrethash]

    mediator.state_transition(
        mediator_state=mediator_state,
        state_change=ReceiveSecretReveal(secret,
                                         payee_channel.partner_state.address),
        channelidentifiers_to_channels=setup.channel_map,
        nodeaddresses_to_networkstates=setup.channels.
        nodeaddresses_to_networkstates,
        pseudo_random_generator=pseudo_random_generator,
        block_number=setup.block_number,
        block_hash=setup.block_hash,
    )
    assert secrethash in payer_channel.partner_state.secrethashes_to_unlockedlocks

    secret_registry_address = factories.make_address()
    transaction_hash = factories.make_address()
    mediator.state_transition(
        mediator_state=mediator_state,
        state_change=ContractReceiveSecretReveal(
            transaction_hash=transaction_hash,
            secret_registry_address=secret_registry_address,
            secrethash=secrethash,
            secret=secret,
            block_number=setup.block_number,
            block_hash=setup.block_hash,
        ),
        channelidentifiers_to_channels=setup.channel_map,
        nodeaddresses_to_networkstates=setup.channels.
        nodeaddresses_to_networkstates,
        pseudo_random_generator=pseudo_random_generator,
        block_number=setup.block_number,
        block_hash=setup.block_hash,
    )
    assert secrethash in payer_channel.partner_state.secrethashes_to_onchain_unlockedlocks

    # Creates a transfer as it was from the *partner*
    send_lock_expired, _ = channel.create_sendexpiredlock(
        sender_end_state=payer_channel.partner_state,
        locked_lock=lock,
        pseudo_random_generator=pseudo_random_generator,
        chain_id=payer_channel.chain_id,
        token_network_identifier=payer_channel.token_network_identifier,
        channel_identifier=payer_channel.identifier,
        recipient=payer_channel.our_state.address,
    )
    assert send_lock_expired
    expired_message = message_from_sendevent(send_lock_expired,
                                             setup.channels.our_address(0))
    expired_message.sign(LocalSigner(setup.channels.partner_privatekeys[0]))
    balance_proof = balanceproof_from_envelope(expired_message)

    message_identifier = message_identifier_from_prng(pseudo_random_generator)
    expired_block_number = channel.get_sender_expiration_threshold(lock)
    mediator.state_transition(
        mediator_state=mediator_state,
        state_change=ReceiveLockExpired(
            balance_proof=balance_proof,
            secrethash=secrethash,
            message_identifier=message_identifier,
        ),
        channelidentifiers_to_channels=setup.channel_map,
        nodeaddresses_to_networkstates=setup.channels.
        nodeaddresses_to_networkstates,
        pseudo_random_generator=pseudo_random_generator,
        block_number=expired_block_number,
        block_hash=factories.make_block_hash(),
    )
    assert secrethash in payer_channel.partner_state.secrethashes_to_onchain_unlockedlocks
def test_regression_mediator_task_no_routes():
    """ The mediator must only be cleared after the waiting transfer's lock has
    been handled.

    If a node receives a transfer to mediate, but there is no route available
    (because there is no sufficient capacity or the partner nodes are offline),
    and a refund is not possible, the mediator task must not be cleared,
    otherwise followup remove expired lock messages wont be processed and the
    nodes will get out of sync.
    """
    pseudo_random_generator = random.Random()

    channels = make_channel_set([
        NettingChannelStateProperties(
            our_state=NettingChannelEndStateProperties(balance=0),
            partner_state=NettingChannelEndStateProperties(
                balance=10,
                address=HOP2,
                privatekey=HOP2_KEY,
            ),
        ),
    ])

    payer_transfer = factories.make_signed_transfer_for(
        channels[0],
        factories.LockedTransferSignedStateProperties(
            sender=HOP2,
            pkey=HOP2_KEY,
            transfer=factories.LockedTransferProperties(expiration=30),
        ))

    init_state_change = ActionInitMediator(
        channels.get_routes(),
        channels.get_route(0),
        payer_transfer,
    )
    init_iteration = mediator.state_transition(
        mediator_state=None,
        state_change=init_state_change,
        channelidentifiers_to_channels=channels.channel_map,
        nodeaddresses_to_networkstates=channels.nodeaddresses_to_networkstates,
        pseudo_random_generator=pseudo_random_generator,
        block_number=5,
        block_hash=factories.make_block_hash(),
    )

    msg = 'The task must not be cleared, even if there is no route to forward the transfer'
    assert init_iteration.new_state is not None, msg
    assert init_iteration.new_state.waiting_transfer.transfer == payer_transfer
    assert search_for_item(init_iteration.events, SendLockedTransfer,
                           {}) is None
    assert search_for_item(init_iteration.events, SendRefundTransfer,
                           {}) is None

    secrethash = UNIT_SECRETHASH
    lock = channels[0].partner_state.secrethashes_to_lockedlocks[secrethash]

    # Creates a transfer as it was from the *partner*
    send_lock_expired, _ = channel.create_sendexpiredlock(
        sender_end_state=channels[0].partner_state,
        locked_lock=lock,
        pseudo_random_generator=pseudo_random_generator,
        chain_id=channels[0].chain_id,
        token_network_identifier=channels[0].token_network_identifier,
        channel_identifier=channels[0].identifier,
        recipient=channels[0].our_state.address,
    )
    assert send_lock_expired
    lock_expired_message = message_from_sendevent(send_lock_expired, HOP1)
    lock_expired_message.sign(LocalSigner(channels.partner_privatekeys[0]))
    balance_proof = balanceproof_from_envelope(lock_expired_message)

    message_identifier = message_identifier_from_prng(pseudo_random_generator)

    # Regression: The mediator must still be able to process the block which
    # expires the lock
    expired_block_number = channel.get_sender_expiration_threshold(lock)
    block_hash = factories.make_block_hash()
    expire_block_iteration = mediator.state_transition(
        mediator_state=init_iteration.new_state,
        state_change=Block(
            block_number=expired_block_number,
            gas_limit=0,
            block_hash=block_hash,
        ),
        channelidentifiers_to_channels=channels.channel_map,
        nodeaddresses_to_networkstates=channels.nodeaddresses_to_networkstates,
        pseudo_random_generator=pseudo_random_generator,
        block_number=expired_block_number,
        block_hash=block_hash,
    )
    assert expire_block_iteration.new_state is not None

    receive_expired_iteration = mediator.state_transition(
        mediator_state=expire_block_iteration.new_state,
        state_change=ReceiveLockExpired(
            balance_proof=balance_proof,
            secrethash=secrethash,
            message_identifier=message_identifier,
        ),
        channelidentifiers_to_channels=channels.channel_map,
        nodeaddresses_to_networkstates=channels.nodeaddresses_to_networkstates,
        pseudo_random_generator=pseudo_random_generator,
        block_number=expired_block_number,
        block_hash=block_hash,
    )

    msg = 'The only used channel had the lock cleared, the task must be cleared'
    assert receive_expired_iteration.new_state is None, msg
    assert secrethash not in channels[
        0].partner_state.secrethashes_to_lockedlocks
def test_regression_mediator_task_no_routes():
    """ The mediator must only be cleared after the waiting transfer's lock has
    been handled.

    If a node receives a transfer to mediate, but there is no route available
    (because there is no sufficient capacity or the partner nodes are offline),
    and a refund is not possible, the mediator task must not be cleared,
    otherwise followup remove expired lock messages wont be processed and the
    nodes will get out of sync.
    """
    pseudo_random_generator = random.Random()

    channels = make_channel_set([
        NettingChannelStateProperties(
            our_state=NettingChannelEndStateProperties(balance=0),
            partner_state=NettingChannelEndStateProperties(
                balance=10,
                address=HOP2,
                privatekey=HOP2_KEY,
            ),
        ),
    ])

    payer_transfer = factories.make_signed_transfer_for(
        channels[0],
        factories.LockedTransferSignedStateProperties(
            sender=HOP2,
            pkey=HOP2_KEY,
            transfer=factories.LockedTransferProperties(expiration=30),
        ))

    init_state_change = ActionInitMediator(
        channels.get_routes(),
        channels.get_route(0),
        payer_transfer,
    )
    init_iteration = mediator.state_transition(
        mediator_state=None,
        state_change=init_state_change,
        channelidentifiers_to_channels=channels.channel_map,
        pseudo_random_generator=pseudo_random_generator,
        block_number=5,
    )

    msg = 'The task must not be cleared, even if there is no route to forward the transfer'
    assert init_iteration.new_state is not None, msg
    assert init_iteration.new_state.waiting_transfer.transfer == payer_transfer
    assert must_contain_entry(init_iteration.events, SendLockedTransfer, {}) is None
    assert must_contain_entry(init_iteration.events, SendRefundTransfer, {}) is None

    secrethash = UNIT_SECRETHASH
    lock = channels[0].partner_state.secrethashes_to_lockedlocks[secrethash]

    # Creates a transfer as it was from the *partner*
    send_lock_expired, _ = channel.create_sendexpiredlock(
        sender_end_state=channels[0].partner_state,
        locked_lock=lock,
        pseudo_random_generator=pseudo_random_generator,
        chain_id=channels[0].chain_id,
        token_network_identifier=channels[0].token_network_identifier,
        channel_identifier=channels[0].identifier,
        recipient=channels[0].our_state.address,
    )
    assert send_lock_expired
    lock_expired_message = message_from_sendevent(send_lock_expired, HOP1)
    lock_expired_message.sign(channels.partner_privatekeys[0])
    balance_proof = balanceproof_from_envelope(lock_expired_message)

    message_identifier = message_identifier_from_prng(pseudo_random_generator)

    # Regression: The mediator must still be able to process the block which
    # expires the lock
    expired_block_number = channel.get_sender_expiration_threshold(lock)
    expire_block_iteration = mediator.state_transition(
        mediator_state=init_iteration.new_state,
        state_change=Block(
            block_number=expired_block_number,
            gas_limit=0,
            block_hash=None,
        ),
        channelidentifiers_to_channels=channels.channel_map,
        pseudo_random_generator=pseudo_random_generator,
        block_number=expired_block_number,
    )
    assert expire_block_iteration.new_state is not None

    receive_expired_iteration = mediator.state_transition(
        mediator_state=expire_block_iteration.new_state,
        state_change=ReceiveLockExpired(
            balance_proof=balance_proof,
            secrethash=secrethash,
            message_identifier=message_identifier,
        ),
        channelidentifiers_to_channels=channels.channel_map,
        pseudo_random_generator=pseudo_random_generator,
        block_number=expired_block_number,
    )

    msg = 'The only used channel had the lock cleared, the task must be cleared'
    assert receive_expired_iteration.new_state is None, msg
    assert secrethash not in channels[0].partner_state.secrethashes_to_lockedlocks
def test_regression_onchain_secret_reveal_must_update_channel_state():
    """ If a secret is learned off-chain and then on-chain, the state of the
    lock must be updated in the channel.
    """
    pseudo_random_generator = random.Random()

    setup = factories.make_transfers_pair(2, block_number=10)

    mediator_state = MediatorTransferState(UNIT_SECRETHASH)
    mediator_state.transfers_pair = setup.transfers_pair

    secret = UNIT_SECRET
    secrethash = UNIT_SECRETHASH
    payer_channel = mediator.get_payer_channel(setup.channel_map, setup.transfers_pair[0])
    payee_channel = mediator.get_payee_channel(setup.channel_map, setup.transfers_pair[0])
    lock = payer_channel.partner_state.secrethashes_to_lockedlocks[secrethash]

    mediator.state_transition(
        mediator_state=mediator_state,
        state_change=ReceiveSecretReveal(secret, payee_channel.partner_state.address),
        channelidentifiers_to_channels=setup.channel_map,
        pseudo_random_generator=pseudo_random_generator,
        block_number=setup.block_number,
    )
    assert secrethash in payer_channel.partner_state.secrethashes_to_unlockedlocks

    secret_registry_address = factories.make_address()
    transaction_hash = factories.make_address()
    mediator.state_transition(
        mediator_state=mediator_state,
        state_change=ContractReceiveSecretReveal(
            transaction_hash,
            secret_registry_address,
            secrethash,
            secret,
            setup.block_number,
        ),
        channelidentifiers_to_channels=setup.channel_map,
        pseudo_random_generator=pseudo_random_generator,
        block_number=setup.block_number,
    )
    assert secrethash in payer_channel.partner_state.secrethashes_to_onchain_unlockedlocks

    # Creates a transfer as it was from the *partner*
    send_lock_expired, _ = channel.create_sendexpiredlock(
        sender_end_state=payer_channel.partner_state,
        locked_lock=lock,
        pseudo_random_generator=pseudo_random_generator,
        chain_id=payer_channel.chain_id,
        token_network_identifier=payer_channel.token_network_identifier,
        channel_identifier=payer_channel.identifier,
        recipient=payer_channel.our_state.address,
    )
    assert send_lock_expired
    expired_message = message_from_sendevent(send_lock_expired, setup.channels.our_address(0))
    expired_message.sign(setup.channels.partner_privatekeys[0])
    balance_proof = balanceproof_from_envelope(expired_message)

    message_identifier = message_identifier_from_prng(pseudo_random_generator)
    expired_block_number = channel.get_sender_expiration_threshold(lock)
    mediator.state_transition(
        mediator_state=mediator_state,
        state_change=ReceiveLockExpired(
            balance_proof=balance_proof,
            secrethash=secrethash,
            message_identifier=message_identifier,
        ),
        channelidentifiers_to_channels=setup.channel_map,
        pseudo_random_generator=pseudo_random_generator,
        block_number=expired_block_number,
    )
    assert secrethash in payer_channel.partner_state.secrethashes_to_onchain_unlockedlocks
示例#43
0
    def start(self):
        """ Start the node synchronously. Raises directly if anything went wrong on startup """
        if not self.stop_event.ready():
            raise RuntimeError(f'{self!r} already started')
        self.stop_event.clear()

        if self.database_dir is not None:
            self.db_lock.acquire(timeout=0)
            assert self.db_lock.is_locked

        # start the registration early to speed up the start
        if self.config['transport_type'] == 'udp':
            endpoint_registration_greenlet = gevent.spawn(
                self.discovery.register,
                self.address,
                self.config['transport']['udp']['external_ip'],
                self.config['transport']['udp']['external_port'],
            )

        storage = sqlite.SQLiteStorage(self.database_path,
                                       serialize.JSONSerializer())
        self.wal = wal.restore_to_state_change(
            transition_function=node.state_transition,
            storage=storage,
            state_change_identifier='latest',
        )

        if self.wal.state_manager.current_state is None:
            log.debug(
                'No recoverable state available, created inital state',
                node=pex(self.address),
            )
            block_number = self.chain.block_number()

            state_change = ActionInitChain(
                random.Random(),
                block_number,
                self.chain.node_address,
                self.chain.network_id,
            )
            self.wal.log_and_dispatch(state_change)
            payment_network = PaymentNetworkState(
                self.default_registry.address,
                [],  # empty list of token network states as it's the node's startup
            )
            state_change = ContractReceiveNewPaymentNetwork(
                constants.EMPTY_HASH,
                payment_network,
            )
            self.handle_state_change(state_change)

            # On first run Raiden needs to fetch all events for the payment
            # network, to reconstruct all token network graphs and find opened
            # channels
            last_log_block_number = 0
        else:
            # The `Block` state change is dispatched only after all the events
            # for that given block have been processed, filters can be safely
            # installed starting from this position without losing events.
            last_log_block_number = views.block_number(
                self.wal.state_manager.current_state)
            log.debug(
                'Restored state from WAL',
                last_restored_block=last_log_block_number,
                node=pex(self.address),
            )

            known_networks = views.get_payment_network_identifiers(
                views.state_from_raiden(self))
            if known_networks and self.default_registry.address not in known_networks:
                configured_registry = pex(self.default_registry.address)
                known_registries = lpex(known_networks)
                raise RuntimeError(
                    f'Token network address mismatch.\n'
                    f'Raiden is configured to use the smart contract '
                    f'{configured_registry}, which conflicts with the current known '
                    f'smart contracts {known_registries}', )

        # Clear ref cache & disable caching
        serialize.RaidenJSONDecoder.ref_cache.clear()
        serialize.RaidenJSONDecoder.cache_object_references = False

        # Restore the current snapshot group
        state_change_qty = self.wal.storage.count_state_changes()
        self.snapshot_group = state_change_qty // SNAPSHOT_STATE_CHANGES_COUNT

        # Install the filters using the correct from_block value, otherwise
        # blockchain logs can be lost.
        self.install_all_blockchain_filters(
            self.default_registry,
            self.default_secret_registry,
            last_log_block_number,
        )

        # Complete the first_run of the alarm task and synchronize with the
        # blockchain since the last run.
        #
        # Notes about setup order:
        # - The filters must be polled after the node state has been primed,
        # otherwise the state changes won't have effect.
        # - The alarm must complete its first run  before the transport is started,
        #  to avoid rejecting messages for unknown channels.
        self.alarm.register_callback(self._callback_new_block)

        # alarm.first_run may process some new channel, which would start_health_check_for
        # a partner, that's why transport needs to be already started at this point
        self.transport.start(self)

        self.alarm.first_run()

        chain_state = views.state_from_raiden(self)
        # Dispatch pending transactions
        pending_transactions = views.get_pending_transactions(chain_state, )
        log.debug(
            'Processing pending transactions',
            num_pending_transactions=len(pending_transactions),
            node=pex(self.address),
        )
        with self.dispatch_events_lock:
            for transaction in pending_transactions:
                try:
                    self.raiden_event_handler.on_raiden_event(
                        self, transaction)
                except RaidenRecoverableError as e:
                    log.error(str(e))
                except RaidenUnrecoverableError as e:
                    if self.config['network_type'] == NetworkType.MAIN:
                        if isinstance(e, InvalidDBData):
                            raise
                        log.error(str(e))
                    else:
                        raise

        self.alarm.start()

        # after transport and alarm is started, send queued messages
        events_queues = views.get_all_messagequeues(chain_state)

        for queue_identifier, event_queue in events_queues.items():
            self.start_health_check_for(queue_identifier.recipient)

            # repopulate identifier_to_results for pending transfers
            for event in event_queue:
                if type(event) == SendDirectTransfer:
                    self.identifier_to_results[
                        event.payment_identifier] = AsyncResult()

                message = message_from_sendevent(event, self.address)
                self.sign(message)
                self.transport.send_async(queue_identifier, message)

        # exceptions on these subtasks should crash the app and bubble up
        self.alarm.link_exception(self.on_error)
        self.transport.link_exception(self.on_error)

        # Health check needs the transport layer
        self.start_neighbours_healthcheck()

        if self.config['transport_type'] == 'udp':
            endpoint_registration_greenlet.get(
            )  # re-raise if exception occurred

        super().start()