def test_invalid_instantiation_action_init_mediator_and_target(additional_args):
    hop_state = HopState(
        node_address=factories.make_address(),
        channel_identifier=factories.make_channel_identifier(),
    )

    route_state = RouteState(
        route=[factories.make_address()], forward_channel_id=factories.make_channel_identifier()
    )

    not_a_route_state = object()
    valid_transfer = factories.create(factories.LockedTransferSignedStateProperties())
    wrong_type_transfer = factories.create(factories.TransferDescriptionProperties())

    with pytest.raises(ValueError):
        ActionInitMediator(
            from_transfer=wrong_type_transfer,
            from_hop=hop_state,
            route_states=[route_state],
            **additional_args,
        )

    with pytest.raises(ValueError):
        ActionInitMediator(
            from_transfer=valid_transfer,
            from_hop=not_a_route_state,
            route_states=[route_state],
            **additional_args,
        )

    with pytest.raises(ValueError):
        ActionInitTarget(transfer=wrong_type_transfer, from_hop=hop_state, **additional_args)

    with pytest.raises(ValueError):
        ActionInitTarget(transfer=valid_transfer, from_hop=not_a_route_state, **additional_args)
Exemple #2
0
    def handle_message_lockedtransfer(
        raiden: "RaidenService", message: LockedTransfer  # pylint: disable=unused-argument
    ) -> List[StateChange]:
        secrethash = message.lock.secrethash
        # We must check if the secret was registered against the latest block,
        # even if the block is forked away and the transaction that registers
        # the secret is removed from the blockchain. The rationale here is that
        # someone else does know the secret, regardless of the chain state, so
        # the node must not use it to start a payment.
        #
        # For this particular case, it's preferable to use `latest` instead of
        # having a specific block_hash, because it's preferable to know if the secret
        # was ever known, rather than having a consistent view of the blockchain.
        registered = raiden.default_secret_registry.is_secret_registered(
            secrethash=secrethash, block_identifier=BLOCK_ID_LATEST
        )
        if registered:
            log.warning(
                f"Ignoring received locked transfer with secrethash {to_hex(secrethash)} "
                f"since it is already registered in the secret registry"
            )
            return []

        assert message.sender, "Invalid message dispatched, it should be signed"

        from_transfer = lockedtransfersigned_from_message(message)
        from_hop = HopState(
            node_address=message.sender,
            # pylint: disable=E1101
            channel_identifier=from_transfer.balance_proof.channel_identifier,
        )
        if message.target == TargetAddress(raiden.address):
            raiden.immediate_health_check_for(Address(message.initiator))
            return [
                ActionInitTarget(
                    from_hop=from_hop,
                    transfer=from_transfer,
                    balance_proof=from_transfer.balance_proof,
                    sender=from_transfer.balance_proof.sender,
                )
            ]
        else:
            route_states = routing.resolve_routes(
                routes=message.metadata.routes,
                token_network_address=from_transfer.balance_proof.token_network_address,
                chain_state=views.state_from_raiden(raiden),
            )
            return [
                ActionInitMediator(
                    from_hop=from_hop,
                    route_states=route_states,
                    from_transfer=from_transfer,
                    balance_proof=from_transfer.balance_proof,
                    sender=from_transfer.balance_proof.sender,
                )
            ]
Exemple #3
0
    def _action_init_mediator(
            self, transfer: LockedTransferSignedState) -> ActionInitMediator:
        initiator_channel = self.address_to_channel[transfer.initiator]
        target_channel = self.address_to_channel[transfer.target]

        return ActionInitMediator(
            [factories.make_route_from_channel(target_channel)],
            factories.make_route_to_channel(initiator_channel),
            transfer,
        )
    def _action_init_mediator(
            self, transfer: LockedTransferSignedState) -> ActionInitMediator:
        initiator_channel = self.address_to_channel[transfer.initiator]
        target_channel = self.address_to_channel[transfer.target]

        return ActionInitMediator(
            route_states=[factories.make_route_from_channel(target_channel)],
            from_hop=factories.make_hop_to_channel(initiator_channel),
            from_transfer=transfer,
            balance_proof=transfer.balance_proof,
            sender=transfer.balance_proof.sender,
        )
Exemple #5
0
def make_init_statechange(from_transfer,
                          from_route,
                          routes,
                          our_address=factories.ADDR):

    block_number = 1
    init_state_change = ActionInitMediator(
        our_address,
        from_transfer,
        RoutesState(routes),
        from_route,
        block_number,
    )
    return init_state_change
Exemple #6
0
    def _action_init_mediator(
        self, transfer: LockedTransferSignedState, client_address
    ) -> WithOurAddress:
        client = self.address_to_client[client_address]
        initiator_channel = client.address_to_channel[transfer.initiator]
        target_channel = client.address_to_channel[transfer.target]

        action = ActionInitMediator(
            route_states=[factories.make_route_from_channel(target_channel)],
            from_hop=factories.make_hop_to_channel(initiator_channel),
            from_transfer=transfer,
            balance_proof=transfer.balance_proof,
            sender=transfer.balance_proof.sender,
        )
        return WithOurAddress(our_address=client_address, data=action)
Exemple #7
0
    def mediate_mediated_transfer(self, message):
        # pylint: disable=too-many-locals
        identifier = message.identifier
        amount = message.lock.amount
        target = message.target
        token = message.token
        graph = self.channelgraphs[token]
        routes = graph.get_best_routes(
            self.address,
            target,
            amount,
            lock_timeout=None,
        )

        available_routes = [
            route
            for route in map(route_to_routestate, routes)
            if route.state == CHANNEL_STATE_OPENED
        ]

        from_channel = graph.partneraddress_channel[message.sender]
        from_route = channel_to_routestate(from_channel, message.sender)

        our_address = self.address
        from_transfer = lockedtransfer_from_message(message)
        route_state = RoutesState(available_routes)
        block_number = self.get_block_number()

        init_mediator = ActionInitMediator(
            our_address,
            from_transfer,
            route_state,
            from_route,
            block_number,
        )

        state_manager = StateManager(mediator.state_transition, None)
        all_events = state_manager.dispatch(init_mediator)

        for event in all_events:
            self.state_machine_event_handler.on_event(event)

        self.identifier_statemanager[identifier].append(state_manager)
Exemple #8
0
def mediator_init(raiden, transfer: LockedTransfer) -> ActionInitMediator:
    from_transfer = lockedtransfersigned_from_message(transfer)
    # Feedback token not used here, will be removed with source routing
    routes, _ = routing.get_best_routes(
        chain_state=views.state_from_raiden(raiden),
        token_network_id=TokenNetworkID(
            from_transfer.balance_proof.token_network_identifier),
        one_to_n_address=raiden.default_one_to_n_address,
        from_address=raiden.address,
        to_address=from_transfer.target,
        amount=PaymentAmount(from_transfer.lock.amount
                             ),  # FIXME: mypy; deprecated through #3863
        previous_address=transfer.sender,
        config=raiden.config,
        privkey=raiden.privkey,
    )
    from_route = RouteState(transfer.sender,
                            from_transfer.balance_proof.channel_identifier)
    return ActionInitMediator(routes, from_route, from_transfer)
Exemple #9
0
def mediator_init(raiden, transfer: LockedTransfer):
    from_transfer = lockedtransfersigned_from_message(transfer)
    routes = routing.get_best_routes(
        chain_state=views.state_from_raiden(raiden),
        token_network_id=TokenNetworkID(
            from_transfer.balance_proof.token_network_identifier),
        from_address=raiden.address,
        to_address=from_transfer.target,
        amount=PaymentAmount(from_transfer.lock.amount
                             ),  # FIXME: mypy; deprecated through #3863
        previous_address=transfer.sender,
        config=raiden.config,
        privkey=raiden.privkey,
    )
    from_route = RouteState(transfer.sender,
                            from_transfer.balance_proof.channel_identifier)
    init_mediator_statechange = ActionInitMediator(routes, from_route,
                                                   from_transfer)
    return init_mediator_statechange
Exemple #10
0
def mediator_init(raiden, transfer: LockedTransfer):
    from_transfer = lockedtransfersigned_from_message(transfer)
    routes = routing.get_best_routes(
        views.state_from_raiden(raiden),
        from_transfer.balance_proof.token_network_identifier,
        raiden.address,
        from_transfer.target,
        from_transfer.lock.amount,
        transfer.sender,
    )
    from_route = RouteState(
        transfer.sender,
        from_transfer.balance_proof.channel_address,
    )
    init_mediator_statechange = ActionInitMediator(
        routes,
        from_route,
        from_transfer,
    )
    return init_mediator_statechange
Exemple #11
0
    def mediate_mediated_transfer(self, message):
        # pylint: disable=too-many-locals
        identifier = message.identifier
        amount = message.lock.amount
        target = message.target
        token = message.token
        graph = self.token_to_channelgraph[token]

        available_routes = get_best_routes(
            graph,
            self.protocol.nodeaddresses_networkstatuses,
            self.address,
            target,
            amount,
            message.sender,
        )

        from_channel = graph.partneraddress_to_channel[message.sender]
        from_route = channel_to_routestate(from_channel, message.sender)

        our_address = self.address
        from_transfer = lockedtransfer_from_message(message)
        route_state = RoutesState(available_routes)
        block_number = self.get_block_number()

        init_mediator = ActionInitMediator(
            our_address,
            from_transfer,
            route_state,
            from_route,
            block_number,
        )

        state_manager = StateManager(mediator.state_transition, None)

        self.state_machine_event_handler.log_and_dispatch(
            state_manager, init_mediator)

        self.identifier_to_statemanagers[identifier].append(state_manager)
Exemple #12
0
def mediator_init(raiden, transfer):
    from_transfer = lockedtransfersigned_from_message(transfer)
    registry_address = raiden.default_registry.address
    routes = routing.get_best_routes(
        views.state_from_raiden(raiden),
        registry_address,
        from_transfer.token,
        raiden.address,
        from_transfer.target,
        from_transfer.lock.amount,
        transfer.sender,
    )
    from_route = RouteState(
        transfer.sender,
        from_transfer.balance_proof.channel_address,
    )
    init_mediator_statechange = ActionInitMediator(
        registry_address,
        routes,
        from_route,
        from_transfer,
    )
    return init_mediator_statechange
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
Exemple #14
0
def test_get_state_change_with_balance_proof():
    """ All state changes which contain a balance proof must be found by when
    querying the database.
    """
    serializer = JSONSerializer
    storage = SQLiteStorage(':memory:', serializer)
    counter = itertools.count()

    lock_expired = ReceiveLockExpired(
        balance_proof=make_signed_balance_proof_from_counter(counter),
        secrethash=sha3(factories.make_secret(next(counter))),
        message_identifier=next(counter),
    )
    unlock = ReceiveUnlock(
        message_identifier=next(counter),
        secret=sha3(factories.make_secret(next(counter))),
        balance_proof=make_signed_balance_proof_from_counter(counter),
    )
    transfer_refund = ReceiveTransferRefund(
        transfer=make_signed_transfer_from_counter(counter),
        routes=list(),
    )
    transfer_refund_cancel_route = ReceiveTransferRefundCancelRoute(
        routes=list(),
        transfer=make_signed_transfer_from_counter(counter),
        secret=sha3(factories.make_secret(next(counter))),
    )
    mediator_from_route, mediator_signed_transfer = make_from_route_from_counter(
        counter)
    action_init_mediator = ActionInitMediator(
        routes=list(),
        from_route=mediator_from_route,
        from_transfer=mediator_signed_transfer,
    )
    target_from_route, target_signed_transfer = make_from_route_from_counter(
        counter)
    action_init_target = ActionInitTarget(
        route=target_from_route,
        transfer=target_signed_transfer,
    )

    statechanges_balanceproofs = [
        (lock_expired, lock_expired.balance_proof),
        (unlock, unlock.balance_proof),
        (transfer_refund, transfer_refund.transfer.balance_proof),
        (transfer_refund_cancel_route,
         transfer_refund_cancel_route.transfer.balance_proof),
        (action_init_mediator,
         action_init_mediator.from_transfer.balance_proof),
        (action_init_target, action_init_target.transfer.balance_proof),
    ]

    timestamp = datetime.utcnow().isoformat(timespec='milliseconds')

    for state_change, _ in statechanges_balanceproofs:
        storage.write_state_change(state_change, timestamp)

    for state_change, balance_proof in statechanges_balanceproofs:
        state_change_record = get_state_change_with_balance_proof(
            storage=storage,
            chain_id=balance_proof.chain_id,
            token_network_identifier=balance_proof.token_network_identifier,
            channel_identifier=balance_proof.channel_identifier,
            sender=balance_proof.sender,
            balance_hash=balance_proof.balance_hash,
        )
        assert state_change_record.data == state_change
Exemple #15
0
def mediator_make_init_action(
        channels: ChannelSet,
        transfer: LockedTransferSignedState) -> ActionInitMediator:
    return ActionInitMediator(channels.get_routes(1), channels.get_route(0),
                              transfer)
Exemple #16
0
def test_mediator_clear_pairs_after_batch_unlock(
    chain_state,
    token_network_state,
    our_address,
):
    """ Regression test for https://github.com/raiden-network/raiden/issues/2932
    The mediator must also clear the transfer pairs once a ReceiveBatchUnlock where
    he is a participant is received.
    """
    open_block_number = 10
    pseudo_random_generator = random.Random()
    pkey, address = factories.make_privkey_address()

    amount = 30
    our_balance = amount + 50
    channel_state = factories.make_channel(
        our_balance=our_balance,
        our_address=our_address,
        partner_balance=our_balance,
        partner_address=address,
        token_network_identifier=token_network_state.address,
    )
    payment_network_identifier = factories.make_payment_network_identifier()

    channel_new_state_change = ContractReceiveChannelNew(
        factories.make_transaction_hash(),
        token_network_state.address,
        channel_state,
        open_block_number,
    )

    channel_new_iteration = token_network.state_transition(
        payment_network_identifier,
        token_network_state,
        channel_new_state_change,
        pseudo_random_generator,
        open_block_number,
    )

    lock_amount = 30
    lock_expiration = 20
    lock_secret = sha3(b'test_end_state')
    lock_secrethash = sha3(lock_secret)
    lock = HashTimeLockState(
        lock_amount,
        lock_expiration,
        lock_secrethash,
    )

    mediated_transfer = make_receive_transfer_mediated(
        channel_state=channel_state,
        privkey=pkey,
        nonce=1,
        transferred_amount=0,
        lock=lock,
    )

    from_route = factories.route_from_channel(channel_state)
    init_mediator = ActionInitMediator(
        routes=[from_route],
        from_route=from_route,
        from_transfer=mediated_transfer,
    )

    node.state_transition(chain_state, init_mediator)

    closed_block_number = open_block_number + 10
    channel_close_state_change = ContractReceiveChannelClosed(
        factories.make_transaction_hash(),
        channel_state.partner_state.address,
        token_network_state.address,
        channel_state.identifier,
        closed_block_number,
    )

    channel_closed_iteration = token_network.state_transition(
        payment_network_identifier,
        channel_new_iteration.new_state,
        channel_close_state_change,
        pseudo_random_generator,
        closed_block_number,
    )

    settle_block_number = closed_block_number + channel_state.settle_timeout + 1
    channel_settled_state_change = ContractReceiveChannelSettled(
        factories.make_transaction_hash(),
        token_network_state.address,
        channel_state.identifier,
        settle_block_number,
    )

    channel_settled_iteration = token_network.state_transition(
        payment_network_identifier,
        channel_closed_iteration.new_state,
        channel_settled_state_change,
        pseudo_random_generator,
        closed_block_number,
    )

    token_network_state_after_settle = channel_settled_iteration.new_state
    ids_to_channels = token_network_state_after_settle.channelidentifiers_to_channels
    assert len(ids_to_channels) == 1
    assert channel_state.identifier in ids_to_channels

    block_number = closed_block_number + 1
    channel_batch_unlock_state_change = ContractReceiveChannelBatchUnlock(
        transaction_hash=factories.make_transaction_hash(),
        token_network_identifier=token_network_state.address,
        participant=our_address,
        partner=address,
        locksroot=lock_secrethash,
        unlocked_amount=lock_amount,
        returned_tokens=0,
        block_number=block_number,
    )
    channel_unlock_iteration = node.state_transition(
        chain_state=chain_state,
        state_change=channel_batch_unlock_state_change,
    )
    chain_state = channel_unlock_iteration.new_state
    token_network_state = views.get_token_network_by_identifier(
        chain_state=chain_state,
        token_network_id=token_network_state.address,
    )
    ids_to_channels = token_network_state.channelidentifiers_to_channels
    assert len(ids_to_channels) == 0

    # Make sure that all is fine in the next block
    block = Block(
        block_number=block_number + 1,
        gas_limit=1,
        block_hash=factories.make_transaction_hash(),
    )
    iteration = node.state_transition(
        chain_state=chain_state,
        state_change=block,
    )
    assert iteration.new_state

    # Make sure that mediator task was cleared during the next block processing
    # since the channel was removed
    mediator_task = chain_state.payment_mapping.secrethashes_to_task.get(
        lock_secrethash)
    assert not mediator_task
Exemple #17
0
def test_mediator_clear_pairs_after_batch_unlock(chain_state,
                                                 token_network_state,
                                                 our_address,
                                                 channel_properties):
    """ Regression test for https://github.com/raiden-network/raiden/issues/2932
    The mediator must also clear the transfer pairs once a ReceiveBatchUnlock where
    he is a participant is received.
    """
    open_block_number = 10
    open_block_hash = factories.make_block_hash()

    properties, pkey = channel_properties
    address = properties.partner_state.address
    channel_state = factories.create(properties)

    channel_new_state_change = ContractReceiveChannelNew(
        transaction_hash=factories.make_transaction_hash(),
        channel_state=channel_state,
        block_number=open_block_number,
        block_hash=open_block_hash,
    )

    channel_new_iteration = token_network.state_transition(
        token_network_state=token_network_state,
        state_change=channel_new_state_change,
        block_number=open_block_number,
        block_hash=open_block_hash,
    )

    lock_amount = 30
    lock_expiration = 20
    lock_secret = sha3(b"test_end_state")
    lock_secrethash = sha3(lock_secret)
    lock = HashTimeLockState(lock_amount, lock_expiration, lock_secrethash)

    mediated_transfer = make_receive_transfer_mediated(
        channel_state=channel_state,
        privkey=pkey,
        nonce=1,
        transferred_amount=0,
        lock=lock)

    from_route = factories.make_route_from_channel(channel_state)
    init_mediator = ActionInitMediator(routes=[from_route],
                                       from_route=from_route,
                                       from_transfer=mediated_transfer)

    node.state_transition(chain_state, init_mediator, None)

    closed_block_number = open_block_number + 10
    closed_block_hash = factories.make_block_hash()
    channel_close_state_change = ContractReceiveChannelClosed(
        transaction_hash=factories.make_transaction_hash(),
        transaction_from=channel_state.partner_state.address,
        canonical_identifier=channel_state.canonical_identifier,
        block_number=closed_block_number,
        block_hash=closed_block_hash,
    )

    channel_closed_iteration = token_network.state_transition(
        token_network_state=channel_new_iteration.new_state,
        state_change=channel_close_state_change,
        block_number=closed_block_number,
        block_hash=closed_block_hash,
    )

    settle_block_number = closed_block_number + channel_state.settle_timeout + 1
    channel_settled_state_change = ContractReceiveChannelSettled(
        transaction_hash=factories.make_transaction_hash(),
        canonical_identifier=channel_state.canonical_identifier,
        block_number=settle_block_number,
        block_hash=factories.make_block_hash(),
        our_onchain_locksroot=factories.make_32bytes(),
        partner_onchain_locksroot=EMPTY_MERKLE_ROOT,
    )

    channel_settled_iteration = token_network.state_transition(
        token_network_state=channel_closed_iteration.new_state,
        state_change=channel_settled_state_change,
        block_number=closed_block_number,
        block_hash=closed_block_hash,
    )

    token_network_state_after_settle = channel_settled_iteration.new_state
    ids_to_channels = token_network_state_after_settle.channelidentifiers_to_channels
    assert len(ids_to_channels) == 1
    assert channel_state.identifier in ids_to_channels

    block_number = closed_block_number + 1
    channel_batch_unlock_state_change = ContractReceiveChannelBatchUnlock(
        transaction_hash=factories.make_transaction_hash(),
        canonical_identifier=channel_state.canonical_identifier,
        participant=address,
        partner=our_address,
        locksroot=lock_secrethash,
        unlocked_amount=lock_amount,
        returned_tokens=0,
        block_number=block_number,
        block_hash=factories.make_block_hash(),
    )
    channel_unlock_iteration = node.state_transition(
        chain_state=chain_state,
        state_change=channel_batch_unlock_state_change,
        storage=None)
    chain_state = channel_unlock_iteration.new_state
    token_network_state = views.get_token_network_by_identifier(
        chain_state=chain_state, token_network_id=token_network_state.address)
    ids_to_channels = token_network_state.channelidentifiers_to_channels
    assert len(ids_to_channels) == 0

    # Make sure that all is fine in the next block
    block = Block(block_number=block_number + 1,
                  gas_limit=1,
                  block_hash=factories.make_transaction_hash())
    iteration = node.state_transition(chain_state=chain_state,
                                      state_change=block,
                                      storage=None)
    assert iteration.new_state

    # Make sure that mediator task was cleared during the next block processing
    # since the channel was removed
    mediator_task = chain_state.payment_mapping.secrethashes_to_task.get(
        lock_secrethash)
    assert not mediator_task
Exemple #18
0
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 = factories.make_channel_set([
        {
            'our_state': {
                'balance': 0
            },
            'partner_state': {
                'balance': 10,
                'address': HOP2
            },
            'open_transaction':
            factories.make_transaction_execution_status(
                finished_block_number=10, ),
        },
    ])

    payer_transfer = factories.make_default_signed_transfer_for(
        channels[0],
        initiator=HOP1,
        expiration=30,
        pkey=HOP2_KEY,
        sender=HOP2,
    )

    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(HOP2_KEY)
    balance_proof = balanceproof_from_envelope(lock_expired_message)

    message_identifier = message_identifier_from_prng(pseudo_random_generator)
    expired_block_number = lock.expiration + DEFAULT_NUMBER_OF_BLOCK_CONFIRMATIONS * 2

    # Regression: The mediator must still be able to process the block which
    # expires the 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
Exemple #19
0
def test_get_state_change_with_balance_proof():
    """ All state changes which contain a balance proof must be found when
    querying the database.
    """
    serializer = JSONSerializer()
    storage = SerializedSQLiteStorage(":memory:", serializer)
    counter = itertools.count()

    balance_proof = make_signed_balance_proof_from_counter(counter)

    lock_expired = ReceiveLockExpired(
        sender=balance_proof.sender,
        balance_proof=balance_proof,
        secrethash=factories.make_secret_hash(next(counter)),
        message_identifier=MessageID(next(counter)),
    )

    received_balance_proof = make_signed_balance_proof_from_counter(counter)
    unlock = ReceiveUnlock(
        sender=received_balance_proof.sender,
        message_identifier=MessageID(next(counter)),
        secret=factories.make_secret(next(counter)),
        balance_proof=received_balance_proof,
    )
    transfer = make_signed_transfer_from_counter(counter)
    transfer_refund = ReceiveTransferRefund(
        transfer=transfer,
        balance_proof=transfer.balance_proof,
        sender=transfer.balance_proof.sender,  # pylint: disable=no-member
    )
    transfer = make_signed_transfer_from_counter(counter)
    transfer_reroute = ActionTransferReroute(
        transfer=transfer,
        balance_proof=transfer.balance_proof,
        sender=transfer.balance_proof.sender,  # pylint: disable=no-member
        secret=sha3(factories.make_secret(next(counter))),
    )
    mediator_from_route, mediator_signed_transfer = make_from_route_from_counter(
        counter)

    action_init_mediator = ActionInitMediator(
        route_states=[
            RouteState(
                route=[factories.make_address(),
                       factories.make_address()],
                forward_channel_id=factories.make_channel_identifier(),
            )
        ],
        from_hop=mediator_from_route,
        from_transfer=mediator_signed_transfer,
        balance_proof=mediator_signed_transfer.balance_proof,
        sender=mediator_signed_transfer.balance_proof.sender,  # pylint: disable=no-member
    )
    target_from_route, target_signed_transfer = make_from_route_from_counter(
        counter)
    action_init_target = ActionInitTarget(
        from_hop=target_from_route,
        transfer=target_signed_transfer,
        balance_proof=target_signed_transfer.balance_proof,
        sender=target_signed_transfer.balance_proof.sender,  # pylint: disable=no-member
    )

    statechanges_balanceproofs = [
        (lock_expired, lock_expired.balance_proof),
        (unlock, unlock.balance_proof),
        (transfer_refund, transfer_refund.transfer.balance_proof),
        (transfer_reroute, transfer_reroute.transfer.balance_proof),
        (action_init_mediator,
         action_init_mediator.from_transfer.balance_proof),
        (action_init_target, action_init_target.transfer.balance_proof),
    ]

    assert storage.count_state_changes() == 0

    state_change_ids = storage.write_state_changes(
        [state_change for state_change, _ in statechanges_balanceproofs])
    assert storage.count_state_changes() == len(statechanges_balanceproofs)

    msg_in_order = "Querying must return state changes in order"
    stored_statechanges_records = storage.get_statechanges_records_by_range(
        RANGE_ALL_STATE_CHANGES)
    assert len(stored_statechanges_records) == 6, msg_in_order

    pair_elements = zip(statechanges_balanceproofs, state_change_ids,
                        stored_statechanges_records)
    for statechange_balanceproof, statechange_id, record in pair_elements:
        assert record.data == statechange_balanceproof[0], msg_in_order
        assert record.state_change_identifier == statechange_id, msg_in_order

    # Make sure state changes are returned in the correct order in which they were stored
    stored_statechanges = storage.get_statechanges_by_range(
        Range(
            stored_statechanges_records[1].state_change_identifier,
            stored_statechanges_records[2].state_change_identifier,
        ))

    assert len(stored_statechanges) == 2
    assert isinstance(stored_statechanges[0], ReceiveUnlock)
    assert isinstance(stored_statechanges[1], ReceiveTransferRefund)

    for state_change, balance_proof in statechanges_balanceproofs:
        state_change_record = get_state_change_with_balance_proof_by_balance_hash(
            storage=storage,
            canonical_identifier=balance_proof.canonical_identifier,
            sender=balance_proof.sender,
            balance_hash=balance_proof.balance_hash,
        )
        assert state_change_record
        assert state_change_record.data == state_change

        state_change_record = get_state_change_with_balance_proof_by_locksroot(
            storage=storage,
            canonical_identifier=balance_proof.canonical_identifier,
            sender=balance_proof.sender,
            locksroot=balance_proof.locksroot,
        )
        assert state_change_record
        assert state_change_record.data == state_change

    storage.close()
Exemple #20
0
def test_regression_mediator_not_update_payer_state_twice():
    """ Regression Test for https://github.com/raiden-network/raiden/issues/3086
    Make sure that after a lock expired the mediator doesn't update the pair
    twice causing EventUnlockClaimFailed to be generated at every block.
    """
    amount = 10
    block_number = 5
    initiator = HOP1
    initiator_key = HOP1_KEY
    mediator_address = HOP2
    target = HOP3
    expiration = 30
    pseudo_random_generator = random.Random()

    payer_channel = factories.make_channel(
        partner_balance=amount,
        our_balance=amount,
        our_address=mediator_address,
        partner_address=initiator,
        token_address=UNIT_TOKEN_ADDRESS,
    )
    payer_route = factories.route_from_channel(payer_channel)

    payer_transfer = factories.make_signed_transfer_for(
        channel_state=payer_channel,
        amount=amount,
        initiator=initiator,
        target=target,
        expiration=expiration,
        secret=UNIT_SECRET,
        sender=initiator,
        pkey=initiator_key,
    )

    payee_channel = factories.make_channel(
        our_balance=amount,
        our_address=mediator_address,
        partner_address=target,
        token_address=UNIT_TOKEN_ADDRESS,
    )
    available_routes = [factories.route_from_channel(payee_channel)]
    channel_map = {
        payee_channel.identifier: payee_channel,
        payer_channel.identifier: payer_channel,
    }

    init_state_change = ActionInitMediator(
        routes=available_routes,
        from_route=payer_route,
        from_transfer=payer_transfer,
    )
    initial_state = None
    iteration = mediator.state_transition(
        mediator_state=initial_state,
        state_change=init_state_change,
        channelidentifiers_to_channels=channel_map,
        pseudo_random_generator=pseudo_random_generator,
        block_number=block_number,
    )
    assert iteration.new_state is not None

    current_state = iteration.new_state
    send_transfer = must_contain_entry(iteration.events, SendLockedTransfer,
                                       {})
    assert send_transfer

    transfer = send_transfer.transfer
    block_expiration_number = transfer.lock.expiration + DEFAULT_NUMBER_OF_BLOCK_CONFIRMATIONS * 2

    block = Block(
        block_number=block_expiration_number,
        gas_limit=1,
        block_hash=factories.make_transaction_hash(),
    )
    iteration = mediator.state_transition(
        mediator_state=current_state,
        state_change=block,
        channelidentifiers_to_channels=channel_map,
        pseudo_random_generator=pseudo_random_generator,
        block_number=block_expiration_number,
    )

    msg = 'At the expiration block we should get an EventUnlockClaimFailed'
    assert must_contain_entry(iteration.events, EventUnlockClaimFailed,
                              {}), msg

    current_state = iteration.new_state
    next_block = Block(
        block_number=block_expiration_number + 1,
        gas_limit=1,
        block_hash=factories.make_transaction_hash(),
    )

    # Initiator receives the secret reveal after the lock expired
    receive_secret = ReceiveSecretReveal(
        secret=UNIT_SECRET,
        sender=payee_channel.partner_state.address,
    )
    iteration = mediator.state_transition(
        mediator_state=current_state,
        state_change=receive_secret,
        channelidentifiers_to_channels=channel_map,
        pseudo_random_generator=pseudo_random_generator,
        block_number=next_block.block_number,
    )
    current_state = iteration.new_state
    lock = payer_transfer.lock
    secrethash = lock.secrethash
    assert secrethash in payer_channel.partner_state.secrethashes_to_lockedlocks
    assert current_state.transfers_pair[0].payee_state == 'payee_expired'
    assert not channel.is_secret_known(payer_channel.partner_state, secrethash)

    safe_to_wait, _ = mediator.is_safe_to_wait(
        lock_expiration=lock.expiration,
        reveal_timeout=payer_channel.reveal_timeout,
        block_number=lock.expiration + 10,
    )

    assert not safe_to_wait

    iteration = mediator.state_transition(
        mediator_state=current_state,
        state_change=next_block,
        channelidentifiers_to_channels=channel_map,
        pseudo_random_generator=pseudo_random_generator,
        block_number=block_expiration_number,
    )
    msg = 'At the next block we should not get the same event'
    assert not must_contain_entry(iteration.events, EventUnlockClaimFailed,
                                  {}), msg
def test_payer_enter_danger_zone_with_transfer_payed():
    """ A mediator may have paid the next hop (payee), and didn't get paid by
    the previous hop (payer).

    When this happens, an assertion must not be hit, because it means the
    transfer must be unlocked on-chain.

    Issue: https://github.com/raiden-network/raiden/issues/1013
    """
    amount = 10
    block_number = 5
    target = HOP2
    expiration = 30
    pseudo_random_generator = random.Random()

    payer_channel = factories.make_channel(
        partner_balance=amount,
        partner_address=UNIT_TRANSFER_SENDER,
        token_address=UNIT_TOKEN_ADDRESS,
    )
    payer_route = factories.route_from_channel(payer_channel)

    payer_transfer = factories.make_signed_transfer_for(
        payer_channel,
        amount,
        HOP1,
        target,
        expiration,
        UNIT_SECRET,
    )

    channel1 = factories.make_channel(
        our_balance=amount,
        token_address=UNIT_TOKEN_ADDRESS,
    )
    channel_map = {
        channel1.identifier: channel1,
        payer_channel.identifier: payer_channel,
    }
    possible_routes = [factories.route_from_channel(channel1)]

    init_state_change = ActionInitMediator(
        possible_routes,
        payer_route,
        payer_transfer,
    )
    initial_state = None
    initial_iteration = mediator.state_transition(
        initial_state,
        init_state_change,
        channel_map,
        pseudo_random_generator,
        block_number,
    )

    send_transfer = must_contain_entry(initial_iteration.events,
                                       SendLockedTransfer, {})
    assert send_transfer

    lock_expiration = send_transfer.transfer.lock.expiration

    new_state = initial_iteration.new_state
    for block_number in range(block_number,
                              lock_expiration - channel1.reveal_timeout):
        block_state_change = Block(
            block_number=block_number,
            gas_limit=1,
            block_hash=factories.make_transaction_hash(),
        )

        block_iteration = mediator.handle_block(
            new_state,
            block_state_change,
            channel_map,
            pseudo_random_generator,
        )
        new_state = block_iteration.new_state

    # send the balance proof, transitioning the payee state to paid
    assert new_state.transfers_pair[0].payee_state == 'payee_pending'
    receive_secret = ReceiveSecretReveal(
        UNIT_SECRET,
        channel1.partner_state.address,
    )
    paid_iteration = mediator.state_transition(
        new_state,
        receive_secret,
        channel_map,
        pseudo_random_generator,
        block_number,
    )
    paid_state = paid_iteration.new_state
    assert paid_state.transfers_pair[0].payee_state == 'payee_balance_proof'

    # move to the block in which the payee lock expires. This must not raise an
    # assertion
    expired_block_number = lock_expiration + 1
    expired_block_state_change = Block(
        block_number=expired_block_number,
        gas_limit=1,
        block_hash=factories.make_transaction_hash(),
    )
    block_iteration = mediator.handle_block(
        paid_state,
        expired_block_state_change,
        channel_map,
        pseudo_random_generator,
    )
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.
    """

    amount = 10
    block_number = 5
    target = HOP2
    expiration = 30
    pseudo_random_generator = random.Random()

    payer_channel = factories.make_channel(
        partner_balance=amount,
        partner_address=HOP2,
        token_address=UNIT_TOKEN_ADDRESS,
    )
    payer_route = factories.route_from_channel(payer_channel)

    payer_transfer = factories.make_signed_transfer_for(
        payer_channel,
        amount,
        HOP1,
        target,
        expiration,
        UNIT_SECRET,
        pkey=HOP2_KEY,
        sender=HOP2,
    )

    available_routes = []
    channel_map = {
        payer_channel.identifier: payer_channel,
    }

    init_state_change = ActionInitMediator(
        available_routes,
        payer_route,
        payer_transfer,
    )
    initial_state = None
    init_iteration = mediator.state_transition(
        initial_state,
        init_state_change,
        channel_map,
        pseudo_random_generator,
        block_number,
    )
    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 = payer_channel.partner_state.secrethashes_to_lockedlocks[secrethash]

    # 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
    lock_expired_message = message_from_sendevent(send_lock_expired, HOP1)
    lock_expired_message.sign(HOP2_KEY)
    balance_proof = balanceproof_from_envelope(lock_expired_message)

    message_identifier = message_identifier_from_prng(pseudo_random_generator)
    expired_block_number = lock.expiration + DEFAULT_NUMBER_OF_BLOCK_CONFIRMATIONS * 2

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

    receive_expired_iteration = mediator.state_transition(
        expire_block_iteration.new_state,
        ReceiveLockExpired(
            sender=payer_channel.partner_state.address,
            balance_proof=balance_proof,
            secrethash=secrethash,
            message_identifier=message_identifier,
        ),
        channel_map,
        pseudo_random_generator,
        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 payer_channel.partner_state.secrethashes_to_lockedlocks
def test_mediator_clear_pairs_after_batch_unlock(chain_state,
                                                 token_network_state,
                                                 our_address,
                                                 channel_properties):
    """ Regression test for https://github.com/raiden-network/raiden/issues/2932
    The mediator must also clear the transfer pairs once a ReceiveBatchUnlock where
    he is a participant is received.
    """
    open_block_number = 10
    open_block_hash = factories.make_block_hash()

    pseudo_random_generator = random.Random()

    properties, pkey = channel_properties
    address = properties.partner_state.address
    channel_state = factories.create(properties)

    channel_new_state_change = ContractReceiveChannelNew(
        transaction_hash=factories.make_transaction_hash(),
        channel_state=channel_state,
        block_number=open_block_number,
        block_hash=open_block_hash,
    )

    channel_new_iteration = token_network.state_transition(
        token_network_state=token_network_state,
        state_change=channel_new_state_change,
        block_number=open_block_number,
        block_hash=open_block_hash,
        pseudo_random_generator=pseudo_random_generator,
    )

    lock_amount = 30
    lock_expiration = 20
    lock_secret = keccak(b"test_end_state")
    lock_secrethash = sha256(lock_secret).digest()
    lock = HashTimeLockState(lock_amount, lock_expiration, lock_secrethash)

    mediated_transfer = make_receive_transfer_mediated(
        channel_state=channel_state,
        privkey=pkey,
        nonce=1,
        transferred_amount=0,
        lock=lock)

    route_state = RouteState(
        route=[
            channel_state.our_state.address,
            channel_state.partner_state.address
        ],
        forward_channel_id=channel_state.canonical_identifier.
        channel_identifier,
    )
    from_hop = factories.make_hop_from_channel(channel_state)
    init_mediator = ActionInitMediator(
        route_states=[route_state],
        from_hop=from_hop,
        from_transfer=mediated_transfer,
        balance_proof=mediated_transfer.balance_proof,
        sender=mediated_transfer.balance_proof.sender,  # pylint: disable=no-member
    )

    node.state_transition(chain_state, init_mediator)

    closed_block_number = open_block_number + 10
    closed_block_hash = factories.make_block_hash()
    channel_close_state_change = ContractReceiveChannelClosed(
        transaction_hash=factories.make_transaction_hash(),
        transaction_from=channel_state.partner_state.address,
        canonical_identifier=channel_state.canonical_identifier,
        block_number=closed_block_number,
        block_hash=closed_block_hash,
    )

    channel_closed_iteration = token_network.state_transition(
        token_network_state=channel_new_iteration.new_state,
        state_change=channel_close_state_change,
        block_number=closed_block_number,
        block_hash=closed_block_hash,
        pseudo_random_generator=pseudo_random_generator,
    )

    settle_block_number = closed_block_number + channel_state.settle_timeout + 1
    channel_settled_state_change = ContractReceiveChannelSettled(
        transaction_hash=factories.make_transaction_hash(),
        canonical_identifier=channel_state.canonical_identifier,
        block_number=settle_block_number,
        block_hash=factories.make_block_hash(),
        our_onchain_locksroot=factories.make_32bytes(),
        partner_onchain_locksroot=LOCKSROOT_OF_NO_LOCKS,
    )

    channel_settled_iteration = token_network.state_transition(
        token_network_state=channel_closed_iteration.new_state,
        state_change=channel_settled_state_change,
        block_number=closed_block_number,
        block_hash=closed_block_hash,
        pseudo_random_generator=pseudo_random_generator,
    )

    token_network_state_after_settle = channel_settled_iteration.new_state
    ids_to_channels = token_network_state_after_settle.channelidentifiers_to_channels
    assert len(ids_to_channels) == 1
    assert channel_state.identifier in ids_to_channels

    block_number = closed_block_number + 1
    channel_batch_unlock_state_change = ContractReceiveChannelBatchUnlock(
        transaction_hash=factories.make_transaction_hash(),
        canonical_identifier=channel_state.canonical_identifier,
        receiver=address,
        sender=our_address,
        locksroot=compute_locksroot(PendingLocksState([bytes(lock.encoded)])),
        unlocked_amount=lock_amount,
        returned_tokens=0,
        block_number=block_number,
        block_hash=factories.make_block_hash(),
    )
    channel_unlock_iteration = node.state_transition(
        chain_state=chain_state,
        state_change=channel_batch_unlock_state_change)
    chain_state = channel_unlock_iteration.new_state
    token_network_state = views.get_token_network_by_address(
        chain_state=chain_state,
        token_network_address=token_network_state.address)
    ids_to_channels = token_network_state.channelidentifiers_to_channels
    assert len(ids_to_channels) == 0

    # Make sure that all is fine in the next block
    block = Block(block_number=block_number + 1,
                  gas_limit=1,
                  block_hash=factories.make_transaction_hash())
    iteration = node.state_transition(chain_state=chain_state,
                                      state_change=block)
    assert iteration.new_state

    # Make sure that mediator task was cleared during the next block processing
    # since the channel was removed
    mediator_task = chain_state.payment_mapping.secrethashes_to_task.get(
        lock_secrethash)
    assert not mediator_task
def test_regression_mediator_not_update_payer_state_twice():
    """ Regression Test for https://github.com/raiden-network/raiden/issues/3086
    Make sure that after a lock expired the mediator doesn't update the pair
    twice causing EventUnlockClaimFailed to be generated at every block.
    """
    pseudo_random_generator = random.Random()

    pair = factories.mediator_make_channel_pair()
    payer_channel, payee_channel = pair.channels
    payer_route = factories.route_from_channel(payer_channel)
    payer_transfer = factories.make_signed_transfer_for(
        payer_channel, LONG_EXPIRATION)

    available_routes = [factories.route_from_channel(payee_channel)]
    init_state_change = ActionInitMediator(
        routes=available_routes,
        from_route=payer_route,
        from_transfer=payer_transfer,
    )
    iteration = mediator.state_transition(
        mediator_state=None,
        state_change=init_state_change,
        channelidentifiers_to_channels=pair.channel_map,
        nodeaddresses_to_networkstates=pair.nodeaddresses_to_networkstates,
        pseudo_random_generator=pseudo_random_generator,
        block_number=5,
        block_hash=factories.make_block_hash(),
    )
    assert iteration.new_state is not None

    current_state = iteration.new_state
    send_transfer = search_for_item(iteration.events, SendLockedTransfer, {})
    assert send_transfer

    transfer = send_transfer.transfer
    block_expiration_number = channel.get_sender_expiration_threshold(
        transfer.lock)

    block = Block(
        block_number=block_expiration_number,
        gas_limit=1,
        block_hash=factories.make_transaction_hash(),
    )
    iteration = mediator.state_transition(
        mediator_state=current_state,
        state_change=block,
        channelidentifiers_to_channels=pair.channel_map,
        nodeaddresses_to_networkstates=pair.nodeaddresses_to_networkstates,
        pseudo_random_generator=pseudo_random_generator,
        block_number=block_expiration_number,
        block_hash=factories.make_block_hash(),
    )

    msg = 'At the expiration block we should get an EventUnlockClaimFailed'
    assert search_for_item(iteration.events, EventUnlockClaimFailed, {}), msg

    current_state = iteration.new_state
    next_block = Block(
        block_number=block_expiration_number + 1,
        gas_limit=1,
        block_hash=factories.make_transaction_hash(),
    )

    # Initiator receives the secret reveal after the lock expired
    receive_secret = ReceiveSecretReveal(
        secret=UNIT_SECRET,
        sender=payee_channel.partner_state.address,
    )
    iteration = mediator.state_transition(
        mediator_state=current_state,
        state_change=receive_secret,
        channelidentifiers_to_channels=pair.channel_map,
        nodeaddresses_to_networkstates=pair.nodeaddresses_to_networkstates,
        pseudo_random_generator=pseudo_random_generator,
        block_number=next_block.block_number,
        block_hash=next_block.block_hash,
    )
    current_state = iteration.new_state
    lock = payer_transfer.lock
    secrethash = lock.secrethash
    assert secrethash in payer_channel.partner_state.secrethashes_to_lockedlocks
    assert current_state.transfers_pair[0].payee_state == 'payee_expired'
    assert not channel.is_secret_known(payer_channel.partner_state, secrethash)

    safe_to_wait, _ = mediator.is_safe_to_wait(
        lock_expiration=lock.expiration,
        reveal_timeout=payer_channel.reveal_timeout,
        block_number=lock.expiration + 10,
    )

    assert not safe_to_wait

    iteration = mediator.state_transition(
        mediator_state=current_state,
        state_change=next_block,
        channelidentifiers_to_channels=pair.channel_map,
        nodeaddresses_to_networkstates=pair.nodeaddresses_to_networkstates,
        pseudo_random_generator=pseudo_random_generator,
        block_number=block_expiration_number,
        block_hash=factories.make_block_hash(),
    )
    msg = 'At the next block we should not get the same event'
    assert not search_for_item(iteration.events, EventUnlockClaimFailed,
                               {}), msg
def test_regression_mediator_send_lock_expired_with_new_block():
    """ The mediator must send the lock expired, but it must **not** clear
    itself if it has not **received** the corresponding message.
    """
    amount = 10
    block_number = 5
    target = HOP2
    expiration = 30
    pseudo_random_generator = random.Random()

    payer_channel = factories.make_channel(
        partner_balance=amount,
        partner_address=UNIT_TRANSFER_SENDER,
        token_address=UNIT_TOKEN_ADDRESS,
    )
    payer_route = factories.route_from_channel(payer_channel)

    payer_transfer = factories.make_signed_transfer_for(
        payer_channel,
        amount,
        HOP1,
        target,
        expiration,
        UNIT_SECRET,
    )

    channel1 = factories.make_channel(
        our_balance=amount,
        token_address=UNIT_TOKEN_ADDRESS,
    )
    available_routes = [factories.route_from_channel(channel1)]
    channel_map = {
        channel1.identifier: channel1,
        payer_channel.identifier: payer_channel,
    }

    init_state_change = ActionInitMediator(
        available_routes,
        payer_route,
        payer_transfer,
    )
    initial_state = None
    init_iteration = mediator.state_transition(
        initial_state,
        init_state_change,
        channel_map,
        pseudo_random_generator,
        block_number,
    )
    assert init_iteration.new_state is not None
    send_transfer = must_contain_entry(init_iteration.events,
                                       SendLockedTransfer, {})
    assert send_transfer

    transfer = send_transfer.transfer

    block_expiration_number = transfer.lock.expiration + DEFAULT_NUMBER_OF_BLOCK_CONFIRMATIONS * 2
    block = Block(
        block_number=block_expiration_number,
        gas_limit=1,
        block_hash=factories.make_transaction_hash(),
    )
    iteration = mediator.state_transition(
        init_iteration.new_state,
        block,
        channel_map,
        pseudo_random_generator,
        block_expiration_number,
    )

    msg = ("The payer's lock has also expired, "
           "but it must not be removed locally (without an Expired lock)")
    assert transfer.lock.secrethash in payer_channel.partner_state.secrethashes_to_lockedlocks, msg

    msg = 'The payer has not yet sent an expired lock, the task can not be cleared yet'
    assert iteration.new_state is not None, msg

    assert must_contain_entry(iteration.events, SendLockExpired, {
        'secrethash': transfer.lock.secrethash,
    })
    assert transfer.lock.secrethash not in channel1.our_state.secrethashes_to_lockedlocks
Exemple #26
0
def test_get_state_change_with_balance_proof():
    """ All state changes which contain a balance proof must be found by when
    querying the database.
    """
    serializer = JSONSerializer
    storage = SerializedSQLiteStorage(":memory:", serializer)
    counter = itertools.count()

    lock_expired = ReceiveLockExpired(
        balance_proof=make_signed_balance_proof_from_counter(counter),
        secrethash=sha3(factories.make_secret(next(counter))),
        message_identifier=next(counter),
    )
    unlock = ReceiveUnlock(
        message_identifier=next(counter),
        secret=sha3(factories.make_secret(next(counter))),
        balance_proof=make_signed_balance_proof_from_counter(counter),
    )
    transfer_refund = ReceiveTransferRefund(
        transfer=make_signed_transfer_from_counter(counter), routes=list())
    transfer_refund_cancel_route = ReceiveTransferRefundCancelRoute(
        routes=list(),
        transfer=make_signed_transfer_from_counter(counter),
        secret=sha3(factories.make_secret(next(counter))),
    )
    mediator_from_route, mediator_signed_transfer = make_from_route_from_counter(
        counter)
    action_init_mediator = ActionInitMediator(
        routes=list(),
        from_route=mediator_from_route,
        from_transfer=mediator_signed_transfer)
    target_from_route, target_signed_transfer = make_from_route_from_counter(
        counter)
    action_init_target = ActionInitTarget(route=target_from_route,
                                          transfer=target_signed_transfer)

    statechanges_balanceproofs = [
        (lock_expired, lock_expired.balance_proof),
        (unlock, unlock.balance_proof),
        (transfer_refund, transfer_refund.transfer.balance_proof),
        (transfer_refund_cancel_route,
         transfer_refund_cancel_route.transfer.balance_proof),
        (action_init_mediator,
         action_init_mediator.from_transfer.balance_proof),
        (action_init_target, action_init_target.transfer.balance_proof),
    ]

    timestamp = datetime.utcnow().isoformat(timespec="milliseconds")

    for state_change, _ in statechanges_balanceproofs:
        storage.write_state_change(state_change, timestamp)

    # Make sure state changes are returned in the correct order in which they were stored
    stored_statechanges = storage.get_statechanges_by_identifier(1, "latest")
    assert isinstance(stored_statechanges[0], ReceiveLockExpired)
    assert isinstance(stored_statechanges[1], ReceiveUnlock)
    assert isinstance(stored_statechanges[2], ReceiveTransferRefund)
    assert isinstance(stored_statechanges[3], ReceiveTransferRefundCancelRoute)
    assert isinstance(stored_statechanges[4], ActionInitMediator)
    assert isinstance(stored_statechanges[5], ActionInitTarget)

    # Make sure state changes are returned in the correct order in which they were stored
    stored_statechanges = storage.get_statechanges_by_identifier(1, 2)
    assert isinstance(stored_statechanges[0], ReceiveLockExpired)
    assert isinstance(stored_statechanges[1], ReceiveUnlock)

    for state_change, balance_proof in statechanges_balanceproofs:
        state_change_record = get_state_change_with_balance_proof_by_balance_hash(
            storage=storage,
            canonical_identifier=balance_proof.canonical_identifier,
            sender=balance_proof.sender,
            balance_hash=balance_proof.balance_hash,
        )
        assert state_change_record.data == state_change