def test_regression_unavailable_nodes_must_be_properly_filtered():
    """The list of available routes provided must be filtered based on the
    network status of the partner node.

    Regression test for: https://github.com/raiden-network/raiden/issues/3567
    """
    block_number = 5
    pseudo_random_generator = random.Random()

    channels = factories.mediator_make_channel_pair()
    payer_transfer = factories.make_signed_transfer_for(
        channels[0], LONG_EXPIRATION)

    all_nodes_offline = {
        channel.partner_state.address: NODE_NETWORK_UNREACHABLE
        for channel in channels.channels
    }

    initial_iteration = mediator.state_transition(
        mediator_state=None,
        state_change=factories.mediator_make_init_action(
            channels, payer_transfer),
        channelidentifiers_to_channels=channels.channel_map,
        nodeaddresses_to_networkstates=all_nodes_offline,
        pseudo_random_generator=pseudo_random_generator,
        block_number=block_number,
        block_hash=factories.make_block_hash(),
    )

    send_transfer = search_for_item(initial_iteration.events,
                                    SendLockedTransfer, {})
    msg = (
        'All available routes are with unavailable nodes, therefore no send '
        'should be produced')
    assert send_transfer is None, msg
예제 #2
0
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.
    """
    pseudo_random_generator = random.Random()

    channels = factories.mediator_make_channel_pair()
    payer_transfer = factories.make_signed_transfer_for(
        channels[0], LONG_EXPIRATION)

    init_iteration = mediator.state_transition(
        mediator_state=None,
        state_change=factories.mediator_make_init_action(
            channels, payer_transfer),
        channelidentifiers_to_channels=channels.channel_map,
        addresses_to_channel=channels.addresses_to_channel(),
        nodeaddresses_to_networkstates=channels.nodeaddresses_to_networkstates,
        pseudo_random_generator=pseudo_random_generator,
        block_number=5,
        block_hash=factories.make_block_hash(),
    )
    assert init_iteration.new_state is not None
    send_transfer = search_for_item(init_iteration.events, SendLockedTransfer,
                                    {})
    assert send_transfer

    transfer = send_transfer.transfer

    block_expiration_number = channel.get_sender_expiration_threshold(
        transfer.lock.expiration)
    block = Block(
        block_number=block_expiration_number,
        gas_limit=1,
        block_hash=factories.make_transaction_hash(),
    )
    iteration = mediator.state_transition(
        mediator_state=init_iteration.new_state,
        state_change=block,
        channelidentifiers_to_channels=channels.channel_map,
        addresses_to_channel=channels.addresses_to_channel(),
        nodeaddresses_to_networkstates=channels.nodeaddresses_to_networkstates,
        pseudo_random_generator=pseudo_random_generator,
        block_number=block_expiration_number,
        block_hash=factories.make_block_hash(),
    )

    msg = ("The payer's lock has also expired, "
           "but it must not be removed locally (without an Expired lock)")
    assert transfer.lock.secrethash in channels[
        0].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 search_for_item(iteration.events, SendLockExpired,
                           {"secrethash": transfer.lock.secrethash})
    assert transfer.lock.secrethash not in channels[
        1].our_state.secrethashes_to_lockedlocks
예제 #3
0
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.
    """
    pseudo_random_generator = random.Random()

    channels = factories.mediator_make_channel_pair()
    payer_transfer = factories.make_default_signed_transfer_for(
        channels[0],
        initiator=HOP1,
        expiration=30,
    )

    init_iteration = mediator.state_transition(
        mediator_state=None,
        state_change=factories.mediator_make_init_action(
            channels, payer_transfer),
        channelidentifiers_to_channels=channels.channel_map,
        pseudo_random_generator=pseudo_random_generator,
        block_number=5,
    )
    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(
        mediator_state=init_iteration.new_state,
        state_change=block,
        channelidentifiers_to_channels=channels.channel_map,
        pseudo_random_generator=pseudo_random_generator,
        block_number=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 channels[
        0].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 channels[
        1].our_state.secrethashes_to_lockedlocks
예제 #4
0
def test_get_state_change_with_transfer_by_secrethash():
    serializer = JSONSerializer()
    storage = SerializedSQLiteStorage(":memory:", serializer)

    mediator_secret, mediator_secrethash = factories.make_secret_with_hash()
    channels = factories.mediator_make_channel_pair()
    mediator_transfer = factories.create(
        factories.LockedTransferSignedStateProperties(
            secret=mediator_secret,
            target=channels.partner_address(1),
            initiator=channels.partner_address(0),
        )
    )
    mediator_state_change = factories.mediator_make_init_action(channels, mediator_transfer)

    target_secret, target_secrethash = factories.make_secret_with_hash()
    from_channel = factories.create(
        factories.NettingChannelStateProperties(
            partner_state=factories.NettingChannelEndStateProperties(
                balance=100, address=factories.make_address()
            )
        )
    )
    target_transfer = factories.create(
        factories.LockedTransferSignedStateProperties(
            secret=target_secret,
            target=channels.our_address(0),
            initiator=channels.partner_address(1),
        )
    )

    target_state_change = ActionInitTarget(
        from_hop=HopState(
            node_address=from_channel.partner_state.address,
            channel_identifier=from_channel.canonical_identifier.channel_identifier,
        ),
        transfer=target_transfer,
        balance_proof=target_transfer.balance_proof,
        sender=target_transfer.balance_proof.sender,  # pylint: disable=no-member
    )

    assert storage.count_state_changes() == 0
    storage.write_state_changes([mediator_state_change, target_state_change])
    assert storage.count_state_changes() == 2

    restored = get_state_change_with_transfer_by_secrethash(storage, mediator_secrethash)
    assert isinstance(restored.data, ActionInitMediator)
    assert restored.data.from_transfer == mediator_transfer

    restored = get_state_change_with_transfer_by_secrethash(storage, target_secrethash)
    assert isinstance(restored.data, ActionInitTarget)
    assert restored.data.transfer == target_transfer
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.
    """
    pseudo_random_generator = random.Random()

    channels = factories.mediator_make_channel_pair()
    payer_transfer = factories.make_signed_transfer_for(channels[0], LONG_EXPIRATION)

    init_iteration = mediator.state_transition(
        mediator_state=None,
        state_change=factories.mediator_make_init_action(channels, payer_transfer),
        channelidentifiers_to_channels=channels.channel_map,
        pseudo_random_generator=pseudo_random_generator,
        block_number=5,
    )
    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 = 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=init_iteration.new_state,
        state_change=block,
        channelidentifiers_to_channels=channels.channel_map,
        pseudo_random_generator=pseudo_random_generator,
        block_number=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 channels[0].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 channels[1].our_state.secrethashes_to_lockedlocks
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
    """
    block_number = 5
    pseudo_random_generator = random.Random()

    channels = factories.mediator_make_channel_pair()
    payer_transfer = factories.make_signed_transfer_for(
        channels[0], LONG_EXPIRATION)

    initial_iteration = mediator.state_transition(
        mediator_state=None,
        state_change=factories.mediator_make_init_action(
            channels, payer_transfer),
        channelidentifiers_to_channels=channels.channel_map,
        nodeaddresses_to_networkstates=channels.nodeaddresses_to_networkstates,
        pseudo_random_generator=pseudo_random_generator,
        block_number=block_number,
        block_hash=factories.make_block_hash(),
    )

    send_transfer = search_for_item(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 - channels[1].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,
            channels.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,
        channels[1].partner_state.address,
    )
    paid_iteration = mediator.state_transition(
        mediator_state=new_state,
        state_change=receive_secret,
        channelidentifiers_to_channels=channels.channel_map,
        nodeaddresses_to_networkstates=channels.nodeaddresses_to_networkstates,
        pseudo_random_generator=pseudo_random_generator,
        block_number=block_number,
        block_hash=factories.make_block_hash(),
    )
    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(
        mediator_state=paid_state,
        state_change=expired_block_state_change,
        channelidentifiers_to_channels=channels.channel_map,
        pseudo_random_generator=pseudo_random_generator,
    )
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_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
    """
    block_number = 5
    pseudo_random_generator = random.Random()

    channels = factories.mediator_make_channel_pair()
    payer_transfer = factories.make_signed_transfer_for(channels[0], LONG_EXPIRATION)

    initial_iteration = mediator.state_transition(
        mediator_state=None,
        state_change=factories.mediator_make_init_action(channels, payer_transfer),
        channelidentifiers_to_channels=channels.channel_map,
        pseudo_random_generator=pseudo_random_generator,
        block_number=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 - channels[1].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,
            channels.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,
        channels[1].partner_state.address,
    )
    paid_iteration = mediator.state_transition(
        mediator_state=new_state,
        state_change=receive_secret,
        channelidentifiers_to_channels=channels.channel_map,
        pseudo_random_generator=pseudo_random_generator,
        block_number=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(
        mediator_state=paid_state,
        state_change=expired_block_state_change,
        channelidentifiers_to_channels=channels.channel_map,
        pseudo_random_generator=pseudo_random_generator,
    )
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,
        pseudo_random_generator=pseudo_random_generator,
        block_number=5,
    )
    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 = 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,
        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=pair.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=pair.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