Exemplo n.º 1
0
def test_fullnetwork(raiden_chain):
    app0, app1, app2 = raiden_chain  # pylint: disable=unbalanced-tuple-unpacking

    asset_address = app0.raiden.chain.default_registry.asset_addresses()[0]

    amount = 80
    random.seed(0)
    direct_transfer(app0, app1, asset_address, amount)
    # Assert default identifier is generated correctly
    fchannel = channel(app0, app1, asset_address)
    last_transfer = get_sent_transfer(fchannel, 0)
    random.seed(0)
    assert_identifier_correct(app0, asset_address, app1.raiden.address, last_transfer.identifier)

    amount = 50
    direct_transfer(app1, app2, asset_address, amount)

    amount = 30
    random.seed(0)
    mediated_transfer(
        app1,
        app2,
        asset_address,
        amount
    )
    # Assert default identifier is generated correctly
    fchannel = channel(app1, app2, asset_address)
    last_transfer = get_sent_transfer(fchannel, 1)
    random.seed(0)
    assert_identifier_correct(app1, asset_address, app2.raiden.address, last_transfer.identifier)
def test_mediated_transfer_events(raiden_network, number_of_nodes, token_addresses, network_wait):
    app0, app1, app2 = raiden_network
    token_address = token_addresses[0]
    chain_state = views.state_from_app(app0)
    payment_network_id = app0.raiden.default_registry.address
    token_network_identifier = views.get_token_network_identifier_by_token_address(
        chain_state,
        payment_network_id,
        token_address,
    )

    amount = 10
    mediated_transfer(
        app0,
        app2,
        token_network_identifier,
        amount,
        timeout=network_wait * number_of_nodes,
    )

    def test_initiator_events():
        initiator_blockevents = app0.raiden.wal.storage.get_events_by_identifier(
            from_identifier=0,
            to_identifier='latest',
        )
        initiator_events = [blocknumber_event[1] for blocknumber_event in initiator_blockevents]
        return (
            must_contain_entry(initiator_events, SendRevealSecret, {}) and
            must_contain_entry(initiator_events, EventUnlockSuccess, {})
        )

    assert wait_until(test_initiator_events, network_wait)

    def test_mediator_events():
        mediator_blockevents = app1.raiden.wal.storage.get_events_by_identifier(
            from_identifier=0,
            to_identifier='latest',
        )
        mediator_events = [blocknumber_event[1] for blocknumber_event in mediator_blockevents]
        return (
            must_contain_entry(mediator_events, EventUnlockSuccess, {}) and
            must_contain_entry(mediator_events, EventUnlockClaimSuccess, {})
        )

    assert wait_until(test_mediator_events, network_wait)

    def test_target_events():
        target_blockevents = app2.raiden.wal.storage.get_events_by_identifier(
            from_identifier=0,
            to_identifier='latest',
        )
        target_events = [blocknumber_event[1] for blocknumber_event in target_blockevents]
        return (
            must_contain_entry(target_events, SendSecretRequest, {}) and
            must_contain_entry(target_events, SendRevealSecret, {}) and
            must_contain_entry(target_events, EventUnlockClaimSuccess, {})
        )

    assert wait_until(test_target_events, network_wait)
Exemplo n.º 3
0
def test_refund_messages(raiden_chain, token_addresses, deposit):
    # The network has the following topology:
    #
    #   App0 <---> App1 <---> App2
    app0, app1, app2 = raiden_chain  # pylint: disable=unbalanced-tuple-unpacking
    token_address = token_addresses[0]
    payment_network_identifier = app0.raiden.default_registry.address
    token_network_identifier = views.get_token_network_identifier_by_token_address(
        views.state_from_app(app0),
        payment_network_identifier,
        token_address,
    )

    # Exhaust the channel App1 <-> App2 (to force the refund transfer)
    exhaust_amount = deposit
    mediated_transfer(
        initiator_app=app1,
        target_app=app2,
        token_network_identifier=token_network_identifier,
        amount=exhaust_amount,
        identifier=1,
    )

    refund_amount = deposit // 2
    identifier = 1
    async_result = app0.raiden.mediated_transfer_async(
        token_network_identifier,
        refund_amount,
        app2.raiden.address,
        identifier,
    )
    assert async_result.wait() is False, 'Must fail, there are no routes available'

    # The transfer from app0 to app2 failed, so the balances did change.
    # Since the refund is not unlocked both channels have the corresponding
    # amount locked (issue #1091)
    send_lockedtransfer = raiden_events_must_contain_entry(
        app0.raiden,
        SendLockedTransfer,
        {'transfer': {'lock': {'amount': refund_amount}}},
    )
    assert send_lockedtransfer

    send_refundtransfer = raiden_events_must_contain_entry(app1.raiden, SendRefundTransfer, {})
    assert send_refundtransfer

    assert_synced_channel_state(
        token_network_identifier,
        app0, deposit, [send_lockedtransfer.transfer.lock],
        app1, deposit, [send_refundtransfer.transfer.lock],
    )

    # This channel was exhausted to force the refund transfer
    assert_synced_channel_state(
        token_network_identifier,
        app1, 0, [],
        app2, deposit * 2, [],
    )
Exemplo n.º 4
0
def test_fullnetwork(deployed_network):
    app0, app1, app2 = deployed_network  # pylint: disable=unbalanced-tuple-unpacking

    asset_address = app0.raiden.chain.default_registry.asset_addresses()[0]

    amount = 80
    direct_transfer(app0, app1, asset_address, amount)

    amount = 50
    direct_transfer(app1, app2, asset_address, amount)

    amount = 30
    mediated_transfer(app1, app2, asset_address, amount)
Exemplo n.º 5
0
def test_mediated_transfer_with_entire_deposit(
        raiden_network,
        number_of_nodes,
        token_addresses,
        deposit,
        network_wait,
        public_and_private_rooms,
):
    app0, app1, app2 = raiden_network
    token_address = token_addresses[0]
    chain_state = views.state_from_app(app0)
    payment_network_id = app0.raiden.default_registry.address
    token_network_identifier = views.get_token_network_identifier_by_token_address(
        chain_state,
        payment_network_id,
        token_address,
    )
    mediated_transfer(
        app0,
        app2,
        token_network_identifier,
        deposit,
        timeout=network_wait * number_of_nodes,
    )

    mediated_transfer(
        app2,
        app0,
        token_network_identifier,
        deposit * 2,
        timeout=network_wait * number_of_nodes,
    )

    with gevent.Timeout(network_wait):
        wait_assert(
            assert_synced_channel_state,
            token_network_identifier,
            app0, deposit * 2, [],
            app1, 0, [],
        )
    with gevent.Timeout(network_wait):
        wait_assert(
            assert_synced_channel_state,
            token_network_identifier,
            app1, deposit * 2, [],
            app2, 0, [],
        )
Exemplo n.º 6
0
def test_mediated_transfer_messages_out_of_order(
        raiden_network,
        number_of_nodes,
        deposit,
        token_addresses,
        network_wait,
        skip_if_not_matrix,
):
    app0, app1, app2 = raiden_network
    _patch_transport(app1.raiden.transport)
    _patch_transport(app2.raiden.transport)
    token_address = token_addresses[0]
    chain_state = views.state_from_app(app0)
    payment_network_id = app0.raiden.default_registry.address
    token_network_identifier = views.get_token_network_identifier_by_token_address(
        chain_state,
        payment_network_id,
        token_address,
    )

    amount = 10
    mediated_transfer(
        app0,
        app2,
        token_network_identifier,
        amount,
        timeout=network_wait * number_of_nodes,
    )

    with gevent.Timeout(network_wait):
        wait_assert(
            assert_synced_channel_state,
            token_network_identifier,
            app0, deposit - amount, [],
            app1, deposit + amount, [],
        )
    with gevent.Timeout(network_wait):
        wait_assert(
            assert_synced_channel_state,
            token_network_identifier,
            app1, deposit - amount, [],
            app2, deposit + amount, [],
        )
Exemplo n.º 7
0
def test_mediated_transfer(
        raiden_network,
        number_of_nodes,
        deposit,
        token_addresses,
        network_wait,
):
    app0, app1, app2 = raiden_network
    token_address = token_addresses[0]
    chain_state = views.state_from_app(app0)
    payment_network_id = app0.raiden.default_registry.address
    token_network_identifier = views.get_token_network_identifier_by_token_address(
        chain_state,
        payment_network_id,
        token_address,
    )

    amount = 10
    mediated_transfer(
        app0,
        app2,
        token_network_identifier,
        amount,
        timeout=network_wait * number_of_nodes,
    )

    wait_assert(
        token_network_identifier,
        app0, deposit - amount, [],
        app1, deposit + amount, [],
        func=assert_synched_channel_state,
        timeout=network_wait,
    )
    wait_assert(
        token_network_identifier,
        app1, deposit - amount, [],
        app2, deposit + amount, [],
        func=assert_synched_channel_state,
        timeout=network_wait,
    )
Exemplo n.º 8
0
def test_api_channel_events(raiden_chain, token_addresses):
    app0, app1 = raiden_chain
    token_address = token_addresses[0]
    token_network_identifier = views.get_token_network_identifier_by_token_address(
        views.state_from_app(app0),
        app0.raiden.default_registry.address,
        token_address,
    )

    amount = 30
    mediated_transfer(
        initiator_app=app0,
        target_app=app1,
        token_network_identifier=token_network_identifier,
        amount=amount,
        identifier=1,
    )

    app0_events = RaidenAPI(app0.raiden).get_blockchain_events_channel(
        token_address,
        app1.raiden.address,
    )

    assert must_have_event(app0_events, {'event': ChannelEvent.DEPOSIT})

    app0_events = app0.raiden.wal.storage.get_events()
    any(isinstance(event, EventPaymentSentSuccess) for event in app0_events)

    app1_events = app1.raiden.wal.storage.get_events()
    any(isinstance(event, EventPaymentReceivedSuccess) for event in app1_events)

    app1_events = RaidenAPI(app1.raiden).get_blockchain_events_channel(
        token_address,
        app0.raiden.address,
    )
    assert must_have_event(app1_events, {'event': ChannelEvent.DEPOSIT})
def test_node_can_settle_if_partner_does_not_call_update_transfer(
    raiden_network,
    number_of_nodes,
    deposit,
    token_addresses,
    network_wait,
    chain_id,
):
    """ A node must be able to settle a channel, even if the partner did not
    call update transfer.

    This test will:
    - Make a transfer from app0 to app1, to make sure there are balance
    proofs available
    - Stop app1, to make sure update is not called.
    - Use app0 to close the channel.
    - Assert that app0 can settle the closed channel, even though app1 didn't
    use the latest balance proof
    """

    app0, app1 = raiden_network
    token_address = token_addresses[0]
    chain_state = views.state_from_app(app0)
    payment_network_id = app0.raiden.default_registry.address
    registry_address = app0.raiden.default_registry.address
    token_network_identifier = views.get_token_network_identifier_by_token_address(
        chain_state=chain_state,
        payment_network_id=payment_network_id,
        token_address=token_address,
    )
    channel_identifier = get_channelstate(app0, app1,
                                          token_network_identifier).identifier

    mediated_transfer(
        initiator_app=app0,
        target_app=app1,
        token_network_identifier=token_network_identifier,
        amount=1,
        timeout=network_wait * number_of_nodes,
    )
    # stop app1 - the test uses token_network_contract now
    app1.stop()
    RaidenAPI(app0.raiden).channel_close(
        registry_address=registry_address,
        token_address=token_address,
        partner_address=app1.raiden.address,
    )
    waiting.wait_for_close(
        raiden=app0.raiden,
        payment_network_id=registry_address,
        token_address=token_address,
        channel_ids=[channel_identifier],
        retry_timeout=app0.raiden.alarm.sleep_time,
    )

    # app1 won't update the channel

    waiting.wait_for_settle(
        raiden=app0.raiden,
        payment_network_id=registry_address,
        token_address=token_address,
        channel_ids=[channel_identifier],
        retry_timeout=app0.raiden.alarm.sleep_time,
    )
    state_changes = app0.raiden.wal.storage.get_statechanges_by_identifier(
        from_identifier=0,
        to_identifier='latest',
    )
    assert search_for_item(
        state_changes, ContractReceiveChannelSettled, {
            'token_network_identifier': token_network_identifier,
            'channel_identifier': channel_identifier,
        })
Exemplo n.º 10
0
def test_refund_messages(raiden_chain, token_addresses, deposit):
    # The network has the following topology:
    #
    #   App0 <---> App1 <---> App2
    app0, app1, app2 = raiden_chain  # pylint: disable=unbalanced-tuple-unpacking
    token_address = token_addresses[0]
    payment_network_identifier = app0.raiden.default_registry.address
    token_network_identifier = views.get_token_network_identifier_by_token_address(
        views.state_from_app(app0),
        payment_network_identifier,
        token_address,
    )

    # Exhaust the channel App1 <-> App2 (to force the refund transfer)
    exhaust_amount = deposit
    mediated_transfer(
        initiator_app=app1,
        target_app=app2,
        token_network_identifier=token_network_identifier,
        amount=exhaust_amount,
        identifier=1,
    )

    refund_amount = deposit // 2
    identifier = 1
    payment_status = app0.raiden.mediated_transfer_async(
        token_network_identifier,
        refund_amount,
        app2.raiden.address,
        identifier,
    )
    msg = 'Must fail, there are no routes available'
    assert payment_status.payment_done.wait() is False, msg

    # The transfer from app0 to app2 failed, so the balances did change.
    # Since the refund is not unlocked both channels have the corresponding
    # amount locked (issue #1091)
    send_lockedtransfer = raiden_events_search_for_item(
        app0.raiden,
        SendLockedTransfer,
        {'transfer': {
            'lock': {
                'amount': refund_amount
            }
        }},
    )
    assert send_lockedtransfer

    send_refundtransfer = raiden_events_search_for_item(
        app1.raiden, SendRefundTransfer, {})
    assert send_refundtransfer

    assert_synced_channel_state(
        token_network_identifier,
        app0,
        deposit,
        [send_lockedtransfer.transfer.lock],
        app1,
        deposit,
        [send_refundtransfer.transfer.lock],
    )

    # This channel was exhausted to force the refund transfer
    assert_synced_channel_state(
        token_network_identifier,
        app1,
        0,
        [],
        app2,
        deposit * 2,
        [],
    )
Exemplo n.º 11
0
def test_receive_lockedtransfer_invalidnonce(
    raiden_network,
    number_of_nodes,
    deposit,
    token_addresses,
    reveal_timeout,
    network_wait,
):

    app0, app1, app2 = raiden_network
    token_address = token_addresses[0]
    token_network_identifier = views.get_token_network_identifier_by_token_address(
        views.state_from_app(app0),
        app0.raiden.default_registry.address,
        token_address,
    )
    channel0 = get_channelstate(app0, app1, token_network_identifier)

    amount = 10
    mediated_transfer(
        app0,
        app2,
        token_network_identifier,
        amount,
        timeout=network_wait * number_of_nodes,
    )

    amount = 10
    payment_identifier = 1
    repeated_nonce = 1
    expiration = reveal_timeout * 2
    mediated_transfer_message = LockedTransfer(
        chain_id=UNIT_CHAIN_ID,
        message_identifier=random.randint(0, UINT64_MAX),
        payment_identifier=payment_identifier,
        nonce=repeated_nonce,
        token_network_address=token_network_identifier,
        token=token_address,
        channel_identifier=channel0.identifier,
        transferred_amount=amount,
        locked_amount=amount,
        recipient=app1.raiden.address,
        locksroot=UNIT_SECRETHASH,
        lock=Lock(amount, expiration, UNIT_SECRETHASH),
        target=app2.raiden.address,
        initiator=app0.raiden.address,
        fee=0,
    )

    sign_and_inject(
        mediated_transfer_message,
        app0.raiden.private_key,
        app0.raiden.address,
        app1,
    )

    wait_assert(
        token_network_identifier,
        app0,
        deposit - amount,
        [],
        app1,
        deposit + amount,
        [],
        func=assert_synched_channel_state,
        timeout=network_wait,
    )
Exemplo n.º 12
0
def test_recovery_unhappy_case(
        raiden_network,
        number_of_nodes,
        deposit,
        token_addresses,
        network_wait,
        skip_if_not_udp,
        retry_timeout,
):
    app0, app1, app2 = raiden_network
    token_address = token_addresses[0]
    chain_state = views.state_from_app(app0)
    payment_network_id = app0.raiden.default_registry.address
    token_network_identifier = views.get_token_network_identifier_by_token_address(
        chain_state,
        payment_network_id,
        token_address,
    )

    # make a few transfers from app0 to app2
    amount = 1
    spent_amount = deposit - 2
    for _ in range(spent_amount):
        mediated_transfer(
            app0,
            app2,
            token_network_identifier,
            amount,
            timeout=network_wait * number_of_nodes,
        )

    app0.raiden.stop()
    host_port = (
        app0.raiden.config['transport']['udp']['host'],
        app0.raiden.config['transport']['udp']['port'],
    )
    socket = server._udp_socket(host_port)

    new_transport = UDPTransport(
        app0.raiden.address,
        app0.discovery,
        socket,
        app0.raiden.transport.throttle_policy,
        app0.raiden.config['transport']['udp'],
    )

    app0.stop()

    RaidenAPI(app1.raiden).channel_close(
        app1.raiden.default_registry.address,
        token_address,
        app0.raiden.address,
    )

    channel01 = views.get_channelstate_for(
        views.state_from_app(app1),
        app1.raiden.default_registry.address,
        token_address,
        app0.raiden.address,
    )

    waiting.wait_for_settle(
        app1.raiden,
        app1.raiden.default_registry.address,
        token_address,
        [channel01.identifier],
        retry_timeout,
    )

    raiden_event_handler = RaidenEventHandler()
    message_handler = MessageHandler()

    app0_restart = App(
        config=app0.config,
        chain=app0.raiden.chain,
        query_start_block=0,
        default_registry=app0.raiden.default_registry,
        default_secret_registry=app0.raiden.default_secret_registry,
        transport=new_transport,
        raiden_event_handler=raiden_event_handler,
        message_handler=message_handler,
        discovery=app0.raiden.discovery,
    )
    del app0  # from here on the app0_restart should be used
    app0_restart.start()

    state_changes = app0_restart.raiden.wal.storage.get_statechanges_by_identifier(
        from_identifier=0,
        to_identifier='latest',
    )

    assert must_contain_entry(state_changes, ContractReceiveChannelSettled, {
        'token_network_identifier': token_network_identifier,
        'channel_identifier': channel01.identifier,
    })
Exemplo n.º 13
0
def test_automatic_dispute(raiden_network, deposit, token_addresses):
    app0, app1 = raiden_network
    registry_address = app0.raiden.default_registry.address
    token_address = token_addresses[0]
    token_network_identifier = views.get_token_network_identifier_by_token_address(
        views.state_from_app(app0),
        app0.raiden.default_registry.address,
        token_address,
    )

    channel0 = get_channelstate(app0, app1, token_network_identifier)
    token_proxy = app0.raiden.chain.token(channel0.token_address)
    initial_balance0 = token_proxy.balance_of(app0.raiden.address)
    initial_balance1 = token_proxy.balance_of(app1.raiden.address)

    amount0_1 = 10
    mediated_transfer(
        initiator_app=app0,
        target_app=app1,
        token_network_identifier=token_network_identifier,
        amount=amount0_1,
    )

    amount1_1 = 50
    mediated_transfer(
        initiator_app=app1,
        target_app=app0,
        token_network_identifier=token_network_identifier,
        amount=amount1_1,
    )

    amount0_2 = 60
    mediated_transfer(
        initiator_app=app0,
        target_app=app1,
        token_network_identifier=token_network_identifier,
        amount=amount0_2,
    )

    # Alice can only provide one of Bob's transfer, so she is incentivized to
    # use the one with the largest transferred_amount.
    RaidenAPI(app0.raiden).channel_close(
        registry_address,
        token_address,
        app1.raiden.address,
    )

    # Bob needs to provide a transfer otherwise its netted balance will be
    # wrong, so he is incentivised to use Alice's transfer with the largest
    # transferred_amount.
    #
    # This is done automatically
    # channel1.external_state.update_transfer(
    #     alice_second_transfer,
    # )

    waiting.wait_for_settle(
        app0.raiden,
        registry_address,
        token_address,
        [channel0.identifier],
        app0.raiden.alarm.sleep_time,
    )

    # check that the channel is properly settled and that Bob's client
    # automatically called updateTransfer() to reflect the actual transactions
    assert token_proxy.balance_of(token_network_identifier) == 0
    total0 = amount0_1 + amount0_2
    total1 = amount1_1
    expected_balance0 = initial_balance0 + deposit - total0 + total1
    expected_balance1 = initial_balance1 + deposit + total0 - total1
    assert token_proxy.balance_of(app0.raiden.address) == expected_balance0
    assert token_proxy.balance_of(app1.raiden.address) == expected_balance1
Exemplo n.º 14
0
def test_fullnetwork(
        raiden_chain,
        token_addresses,
        deposit,
        settle_timeout,
        reveal_timeout):
    # pylint: disable=too-many-locals,too-many-statements

    # The network has the following topology:
    #
    #   App0 <---> App1
    #    ^          ^
    #    |          |
    #    v          v
    #   App3 <---> App2

    token_address = token_addresses[0]

    app0, app1, app2, app3 = raiden_chain  # pylint: disable=unbalanced-tuple-unpacking
    channel_0_1 = channel(app0, app1, token_address)
    channel_3_2 = channel(app3, app2, token_address)
    channel_0_3 = channel(app0, app3, token_address)

    # Exhaust the channel deposit (to force the mediated transfer to go backwards)
    amount = deposit
    direct_transfer(app0, app1, token_address, amount, identifier=1)
    assert get_sent_transfer(channel_0_1, 0).transferred_amount == amount

    amount = int(deposit / 2.)
    mediated_transfer(
        app0,
        app2,
        token_address,
        amount
    )

    gevent.sleep(0.5)

    # This is the only possible path, the transfer must go backwards
    assert_path_mediated_transfer(
        get_sent_transfer(channel_0_3, 0),
        get_sent_transfer(channel_3_2, 0),
    )

    app0_state_changes = [
        change[1]
        for change in get_all_state_changes(app0.raiden.transaction_log)
    ]

    app0_events = [
        event.event_object
        for event in get_all_state_events(app0.raiden.transaction_log)
    ]

    secret = None
    for event in app0_events:
        if isinstance(event, SendRevealSecret):
            secret = event.secret

    assert secret is not None
    hashlock = sha3(secret)

    # app0 initiates the direct transfer and mediated_transfer
    assert must_contain_entry(app0_state_changes, ActionInitInitiator, {
        'our_address': app0.raiden.address,
        'transfer': {
            'amount': amount,
            'token': token_address,
            'initiator': app0.raiden.address,
            'target': app2.raiden.address,
            'expiration': None,
            'hashlock': None,
            'secret': None,
        }
    })

    # Of these 2 the state machine will in the future choose the one with the most
    # available balance
    not_taken_route = RouteState(
        state='opened',
        node_address=app1.raiden.address,
        channel_address=channel_0_1.channel_address,
        available_balance=deposit,
        settle_timeout=settle_timeout,
        reveal_timeout=reveal_timeout,
        closed_block=None,
    )

    taken_route = RouteState(
        state='opened',
        node_address=app3.raiden.address,
        channel_address=channel_0_3.channel_address,
        available_balance=deposit,
        settle_timeout=settle_timeout,
        reveal_timeout=reveal_timeout,
        closed_block=None,
    )

    for state_change in app0_state_changes:
        if isinstance(state_change, ActionInitMediator):
            assert taken_route in state_change.routes.available_routes
            assert not_taken_route not in state_change.routes.available_routes

    # app1 received one direct transfers
    app1_state_changes = [
        change[1]
        for change in get_all_state_changes(app1.raiden.transaction_log)
    ]
    assert must_contain_entry(app1_state_changes, ReceiveBalanceProof, {})
    assert must_contain_entry(app1_state_changes, ReceiveTransferDirect, {})

    app2_state_changes = [
        change[1]
        for change in get_all_state_changes(app2.raiden.transaction_log)
    ]

    assert must_contain_entry(app2_state_changes, ActionInitTarget, {
        'our_address': app2.raiden.address,
        'from_route': {
            'state': 'opened',
            'node_address': app3.raiden.address,
            'channel_address': channel_3_2.channel_address,
            'available_balance': deposit,
            'settle_timeout': settle_timeout,
            'reveal_timeout': reveal_timeout,
            'closed_block': None
        },
        'from_transfer': {
            'amount': amount,
            'hashlock': hashlock,
            'token': token_address,
            'initiator': app0.raiden.address,
            'target': app2.raiden.address,
        }
    })

    assert must_contain_entry(app2_state_changes, ReceiveSecretReveal, {
        'sender': app0.raiden.address,
        'secret': secret,
    })

    assert must_contain_entry(app2_state_changes, ReceiveSecretReveal, {
        'sender': app3.raiden.address,
        'secret': secret,
    })

    app2_events = [
        event.event_object
        for event in get_all_state_events(app2.raiden.transaction_log)
    ]

    assert must_contain_entry(app2_events, SendSecretRequest, {
        'amount': amount,
        'hashlock': hashlock,
        'receiver': app0.raiden.address,
    })

    assert must_contain_entry(app2_events, SendRevealSecret, {
        'token': token_address,
        'secret': secret,
        'receiver': app3.raiden.address,
        'sender': app2.raiden.address,
    })

    assert must_contain_entry(app0_state_changes, ReceiveSecretRequest, {
        'amount': amount,
        'sender': app2.raiden.address,
        'hashlock': hashlock,
    })

    assert must_contain_entry(app0_state_changes, ReceiveSecretReveal, {
        'sender': app3.raiden.address,
        'secret': secret,
    })

    assert must_contain_entry(app0_events, EventTransferSentSuccess, {})

    assert must_contain_entry(app0_events, SendMediatedTransfer, {
        'token': token_address,
        'amount': amount,
        'hashlock': hashlock,
        'initiator': app0.raiden.address,
        'target': app2.raiden.address,
        'receiver': app3.raiden.address,
    })

    assert must_contain_entry(app0_events, SendRevealSecret, {
        'secret': secret,
        'token': token_address,
        'receiver': app2.raiden.address,
        'sender': app0.raiden.address,
    })

    assert must_contain_entry(app0_events, SendBalanceProof, {
        'token': token_address,
        'channel_address': channel_0_3.channel_address,
        'receiver': app3.raiden.address,
        'secret': secret,
    })

    assert must_contain_entry(app0_events, EventTransferSentSuccess, {})
    assert must_contain_entry(app0_events, EventUnlockSuccess, {
        'hashlock': hashlock,
    })

    app3_state_changes = [
        change[1]
        for change in get_all_state_changes(app3.raiden.transaction_log)
    ]

    assert must_contain_entry(app3_state_changes, ActionInitMediator, {
        'our_address': app3.raiden.address,
        'from_route': {
            'state': 'opened',
            'node_address': app0.raiden.address,
            'channel_address': channel_0_3.channel_address,
            'available_balance': deposit,
            'settle_timeout': settle_timeout,
            'reveal_timeout': reveal_timeout,
            'closed_block': None,
        },
        'from_transfer': {
            'amount': amount,
            'hashlock': hashlock,
            'token': token_address,
            'initiator': app0.raiden.address,
            'target': app2.raiden.address,
        }
    })

    assert must_contain_entry(app3_state_changes, ReceiveSecretReveal, {
        'sender': app2.raiden.address,
        'secret': secret,
    })

    assert must_contain_entry(app3_state_changes, ReceiveSecretReveal, {
        'sender': app2.raiden.address,
        'secret': secret,
    })

    app3_events = [
        event.event_object
        for event in get_all_state_events(app3.raiden.transaction_log)
    ]

    assert must_contain_entry(app3_events, SendMediatedTransfer, {
        'token': token_address,
        'amount': amount,
        'hashlock': hashlock,
        'initiator': app0.raiden.address,
        'target': app2.raiden.address,
        'receiver': app2.raiden.address,
    })

    assert must_contain_entry(app3_events, SendRevealSecret, {
        'secret': secret,
        'token': token_address,
        'receiver': app0.raiden.address,
        'sender': app3.raiden.address,
    })

    assert must_contain_entry(app3_events, SendBalanceProof, {
        'token': token_address,
        'channel_address': channel_3_2.channel_address,
        'receiver': app2.raiden.address,
        'secret': secret,
    })
    assert must_contain_entry(app3_events, EventUnlockSuccess, {})
Exemplo n.º 15
0
def test_node_can_settle_if_close_didnt_use_any_balance_proof(
        raiden_network,
        number_of_nodes,
        deposit,
        token_addresses,
        network_wait,
):
    """ A node must be able to settle a channel, even if the partner used an
    old balance proof to close it.

    This test will:
    - Make a transfer from app0 to app1, to make sure there are balance
    proofs available
    - Call close manually in behalf of app1, without any balance proof data
    - Assert that app0 can settle the closed channel, even though app1 didn't
    use the latest balance proof
    """

    app0, app1 = raiden_network
    token_address = token_addresses[0]
    chain_state = views.state_from_app(app0)
    payment_network_id = app0.raiden.default_registry.address
    registry_address = app0.raiden.default_registry.address
    token_network_identifier = views.get_token_network_identifier_by_token_address(
        chain_state=chain_state,
        payment_network_id=payment_network_id,
        token_address=token_address,
    )
    channel_identifier = get_channelstate(app0, app1, token_network_identifier).identifier

    # make a transfer from app0 to app1 so that app1 is supposed to have a non
    # empty balance hash
    mediated_transfer(
        initiator_app=app0,
        target_app=app1,
        token_network_identifier=token_network_identifier,
        amount=1,
        timeout=network_wait * number_of_nodes,
    )
    # stop app1 - the test uses token_network_contract now
    app1.stop()
    token_network_contract = TokenNetwork(
        jsonrpc_client=app1.raiden.chain.client,
        token_network_address=token_network_identifier,
        contract_manager=app1.raiden.contract_manager,
    )

    # app1 closes the channel with an empty hash instead of the expected hash
    # of the transferred amount from app0
    token_network_contract.close(
        channel_identifier=channel_identifier,
        partner=app0.raiden.address,
        balance_hash=EMPTY_HASH,
        nonce=0,
        additional_hash=EMPTY_HASH,
        signature=EMPTY_SIGNATURE,
    )
    waiting.wait_for_close(
        raiden=app0.raiden,
        payment_network_id=registry_address,
        token_address=token_address,
        channel_ids=[channel_identifier],
        retry_timeout=app0.raiden.alarm.sleep_time,
    )
    waiting.wait_for_settle(
        raiden=app0.raiden,
        payment_network_id=registry_address,
        token_address=token_address,
        channel_ids=[channel_identifier],
        retry_timeout=app0.raiden.alarm.sleep_time,
    )
    state_changes = app0.raiden.wal.storage.get_statechanges_by_identifier(
        from_identifier=0,
        to_identifier='latest',
    )
    assert must_contain_entry(state_changes, ContractReceiveChannelSettled, {
        'token_network_identifier': token_network_identifier,
        'channel_identifier': channel_identifier,
    })
Exemplo n.º 16
0
def test_recovery_unhappy_case(
    raiden_network,
    number_of_nodes,
    deposit,
    token_addresses,
    network_wait,
    skip_if_not_udp,
    retry_timeout,
):
    app0, app1, app2 = raiden_network
    token_address = token_addresses[0]
    node_state = views.state_from_app(app0)
    payment_network_id = app0.raiden.default_registry.address
    token_network_identifier = views.get_token_network_identifier_by_token_address(
        node_state,
        payment_network_id,
        token_address,
    )

    # make a few transfers from app0 to app2
    amount = 1
    spent_amount = deposit - 2
    for _ in range(spent_amount):
        mediated_transfer(
            app0,
            app2,
            token_network_identifier,
            amount,
            timeout=network_wait * number_of_nodes,
        )

    app0.raiden.stop()
    host_port = (app0.raiden.config['host'], app0.raiden.config['port'])
    socket = server._udp_socket(host_port)

    new_transport = UDPTransport(
        app0.discovery,
        socket,
        app0.raiden.transport.throttle_policy,
        app0.raiden.config['transport'],
    )

    app0.stop()

    RaidenAPI(app1.raiden).channel_close(
        app1.raiden.default_registry.address,
        token_address,
        app0.raiden.address,
    )

    channel01 = views.get_channelstate_for(
        views.state_from_app(app1),
        app1.raiden.default_registry.address,
        token_address,
        app0.raiden.address,
    )

    waiting.wait_for_settle(
        app1.raiden,
        app1.raiden.default_registry.address,
        token_address,
        [channel01.identifier],
        retry_timeout,
    )

    app0_restart = App(
        app0.config,
        app0.raiden.chain,
        app0.raiden.default_registry,
        app0.raiden.default_secret_registry,
        new_transport,
        app0.raiden.discovery,
    )
    del app0  # from here on the app0_restart should be used

    assert_synched_channel_state(
        token_network_identifier,
        app0_restart,
        deposit - spent_amount,
        [],
        app1,
        deposit + spent_amount,
        [],
    )
    assert_synched_channel_state(
        token_network_identifier,
        app1,
        deposit - spent_amount,
        [],
        app2,
        deposit + spent_amount,
        [],
    )
Exemplo n.º 17
0
def test_refund_transfer(raiden_chain, token_addresses, deposit, network_wait):
    """A failed transfer must send a refund back.

    TODO:
        - Unlock the token on refund #1091
        - Clear the merkletree and update the locked amount #193
        - Remove the refund message type #490"""
    # Topology:
    #
    #  0 -> 1 -> 2
    #
    app0, app1, app2 = raiden_chain
    token_address = token_addresses[0]

    # make a transfer to test the path app0 -> app1 -> app2
    identifier_path = 1
    amount_path = 1
    mediated_transfer(
        app0,
        app2,
        token_address,
        amount_path,
        identifier_path,
        timeout=network_wait,
    )

    # drain the channel app1 -> app2
    identifier_drain = 2
    amount_drain = deposit * 8 // 10
    direct_transfer(
        app1,
        app2,
        token_address,
        amount_drain,
        identifier_drain,
        timeout=network_wait,
    )

    # wait for the nodes to sync
    gevent.sleep(0.2)

    assert_synched_channel_state(
        token_address,
        app0,
        deposit - amount_path,
        [],
        app1,
        deposit + amount_path,
        [],
    )
    assert_synched_channel_state(
        token_address,
        app1,
        deposit - amount_path - amount_drain,
        [],
        app2,
        deposit + amount_path + amount_drain,
        [],
    )

    # app0 -> app1 -> app2 is the only available path, but the channel app1 ->
    # app2 doesn't have capacity, so a refund will be sent on app1 -> app0
    identifier_refund = 3
    amount_refund = 50
    async_result = app0.raiden.mediated_transfer_async(
        token_address,
        amount_refund,
        app2.raiden.address,
        identifier_refund,
    )
    assert async_result.wait(
    ) is False, 'there is no path with capacity, the transfer must fail'

    gevent.sleep(0.2)

    # A lock structure with the correct amount
    app0_messages = app0.raiden.protocol.transport.get_sent_messages(
        app0.raiden.address)
    mediated_message = list(message for message in app0_messages
                            if isinstance(message, LockedTransfer)
                            and message.target == app2.raiden.address)[-1]
    assert mediated_message

    app1_messages = app1.raiden.protocol.transport.get_sent_messages(
        app1.raiden.address)
    refund_message = next(message for message in app1_messages
                          if isinstance(message, RefundTransfer)
                          and message.recipient == app0.raiden.address)
    assert refund_message

    assert mediated_message.lock.amount == refund_message.lock.amount
    assert mediated_message.lock.secrethash == refund_message.lock.secrethash
    assert mediated_message.lock.expiration > refund_message.lock.expiration

    # Both channels have the amount locked because of the refund message
    assert_synched_channel_state(
        token_address,
        app0,
        deposit - amount_path,
        [lockstate_from_lock(mediated_message.lock)],
        app1,
        deposit + amount_path,
        [lockstate_from_lock(refund_message.lock)],
    )
    assert_synched_channel_state(
        token_address,
        app1,
        deposit - amount_path - amount_drain,
        [],
        app2,
        deposit + amount_path + amount_drain,
        [],
    )
Exemplo n.º 18
0
def test_refund_transfer(raiden_chain, number_of_nodes, token_addresses, deposit, network_wait):
    """A failed transfer must send a refund back.

    TODO:
        - Unlock the token on refund #1091
        - Clear the merkletree and update the locked amount #193
        - Remove the refund message type #490"""
    # Topology:
    #
    #  0 -> 1 -> 2
    #
    app0, app1, app2 = raiden_chain
    token_address = token_addresses[0]
    payment_network_identifier = app0.raiden.default_registry.address
    token_network_identifier = views.get_token_network_identifier_by_token_address(
        views.state_from_app(app0),
        payment_network_identifier,
        token_address,
    )

    # make a transfer to test the path app0 -> app1 -> app2
    identifier_path = 1
    amount_path = 1
    mediated_transfer(
        app0,
        app2,
        token_network_identifier,
        amount_path,
        identifier_path,
        timeout=network_wait * number_of_nodes,
    )

    # drain the channel app1 -> app2
    identifier_drain = 2
    amount_drain = deposit * 8 // 10
    direct_transfer(
        app1,
        app2,
        token_network_identifier,
        amount_drain,
        identifier_drain,
        timeout=network_wait,
    )

    # wait for the nodes to sync
    gevent.sleep(0.2)

    assert_synched_channel_state(
        token_network_identifier,
        app0, deposit - amount_path, [],
        app1, deposit + amount_path, [],
    )
    assert_synched_channel_state(
        token_network_identifier,
        app1, deposit - amount_path - amount_drain, [],
        app2, deposit + amount_path + amount_drain, [],
    )

    # app0 -> app1 -> app2 is the only available path, but the channel app1 ->
    # app2 doesn't have capacity, so a refund will be sent on app1 -> app0
    identifier_refund = 3
    amount_refund = 50
    async_result = app0.raiden.mediated_transfer_async(
        token_network_identifier,
        amount_refund,
        app2.raiden.address,
        identifier_refund,
    )
    assert async_result.wait() is False, 'there is no path with capacity, the transfer must fail'

    gevent.sleep(0.2)

    # A lock structure with the correct amount

    send_locked = raiden_events_must_contain_entry(
        app0.raiden,
        SendLockedTransfer,
        {'transfer': {'lock': {'amount': amount_refund}}},
    )
    assert send_locked

    send_refund = raiden_events_must_contain_entry(app1.raiden, SendRefundTransfer, {})
    assert send_refund

    lock = send_locked.transfer.lock
    refund_lock = send_refund.lock
    assert lock.amount == refund_lock.amount
    assert lock.secrethash
    assert lock.expiration

    # Both channels have the amount locked because of the refund message
    assert_synched_channel_state(
        token_network_identifier,
        app0, deposit - amount_path, [lockstate_from_lock(lock)],
        app1, deposit + amount_path, [lockstate_from_lock(refund_lock)],
    )
    assert_synched_channel_state(
        token_network_identifier,
        app1, deposit - amount_path - amount_drain, [],
        app2, deposit + amount_path + amount_drain, [],
    )
Exemplo n.º 19
0
def test_fullnetwork(raiden_chain, token_addresses, deposit, settle_timeout,
                     reveal_timeout):

    # The network has the following topology:
    #
    #   App0 <---> App1
    #    ^          ^
    #    |          |
    #    v          v
    #   App3 <---> App2

    token_address = token_addresses[0]

    app0, app1, app2, app3 = raiden_chain  # pylint: disable=unbalanced-tuple-unpacking
    channel_0_1 = channel(app0, app1, token_address)
    channel_3_2 = channel(app3, app2, token_address)
    channel_0_3 = channel(app0, app3, token_address)

    # Exhaust the channel deposit (to force the mediated transfer to go backwards)
    amount = deposit
    direct_transfer(app0, app1, token_address, amount)
    assert get_sent_transfer(channel_0_1, 0).transferred_amount == amount

    amount = int(deposit / 2.)
    mediated_transfer(app0, app2, token_address, amount)

    # This is the only possible path, the transfer must go backwards
    assert_path_mediated_transfer(
        get_sent_transfer(channel_0_3, 0),
        get_sent_transfer(channel_3_2, 0),
    )

    # Now let's query the WAL to see if the state changes were logged as expected
    app0_state_changes = [
        change[1]
        for change in get_all_state_changes(app0.raiden.transaction_log)
        if not isinstance(change[1], Block)
    ]
    app0_events = [
        event.event_object
        for event in get_all_state_events(app0.raiden.transaction_log)
    ]
    app1_state_changes = [
        change[1]
        for change in get_all_state_changes(app1.raiden.transaction_log)
        if not isinstance(change[1], Block)
    ]
    app1_events = [
        event.event_object
        for event in get_all_state_events(app1.raiden.transaction_log)
    ]
    app2_state_changes = [
        change[1]
        for change in get_all_state_changes(app2.raiden.transaction_log)
        if not isinstance(change[1], Block)
    ]
    app2_events = [
        event.event_object
        for event in get_all_state_events(app2.raiden.transaction_log)
    ]
    app3_state_changes = [
        change[1]
        for change in get_all_state_changes(app3.raiden.transaction_log)
        if not isinstance(change[1], Block)
    ]
    app3_events = [
        event.event_object
        for event in get_all_state_events(app3.raiden.transaction_log)
    ]

    # app1 received one direct transfers
    assert len(app1_state_changes) == 1
    assert len(app1_events) == 1

    # app0 initiates the direct transfer and mediated_transfer
    assert len(app0_state_changes) == 4
    assert isinstance(app0_state_changes[1], ActionInitInitiator)
    assert app0_state_changes[1].our_address == app0.raiden.address
    assert app0_state_changes[1].transfer.amount == amount
    assert app0_state_changes[1].transfer.token == token_address
    assert app0_state_changes[1].transfer.initiator == app0.raiden.address
    assert app0_state_changes[1].transfer.target == app2.raiden.address
    # The ActionInitInitiator state change does not have the following fields populated.
    # They get populated via an event during the processing of the state change inside
    # this function: mediated_transfer.mediated_transfer.initiator.try_new_route()
    assert app0_state_changes[1].transfer.expiration is None
    assert app0_state_changes[1].transfer.hashlock is None
    assert app0_state_changes[1].transfer.secret is None
    # We should have one available route
    assert len(app0_state_changes[1].routes.available_routes) == 1
    assert len(app0_state_changes[1].routes.ignored_routes) == 0
    assert len(app0_state_changes[1].routes.refunded_routes) == 0
    assert len(app0_state_changes[1].routes.canceled_routes) == 0
    # Of these 2 the state machine will in the future choose the one with the most
    # available balance
    not_taken_route = RouteState(
        state='opened',
        node_address=app1.raiden.address,
        channel_address=channel_0_1.channel_address,
        available_balance=deposit,
        settle_timeout=settle_timeout,
        reveal_timeout=reveal_timeout,
        closed_block=None,
    )
    taken_route = RouteState(
        state='opened',
        node_address=app3.raiden.address,
        channel_address=channel_0_3.channel_address,
        available_balance=deposit,
        settle_timeout=settle_timeout,
        reveal_timeout=reveal_timeout,
        closed_block=None,
    )
    assert taken_route in app0_state_changes[1].routes.available_routes
    assert not_taken_route not in app0_state_changes[1].routes.available_routes

    # app0 will also receive a secret request from the target
    assert isinstance(app0_state_changes[2], ReceiveSecretRequest)
    assert app0_state_changes[2].amount == amount
    assert app0_state_changes[2].sender == app2.raiden.address
    hashlock = app0_state_changes[2].hashlock

    # app0 will also receive a secret reveal from the immediate neighbour
    assert isinstance(app0_state_changes[3], ReceiveSecretReveal)
    assert app0_state_changes[3].sender == app3.raiden.address
    secret = app0_state_changes[3].secret
    assert sha3(secret) == hashlock

    assert len(app0_events) == 6

    # Direct transfer
    assert isinstance(app0_events[0], EventTransferSentSuccess)

    # not checking the expiration and identifier
    assert isinstance(app0_events[1], SendMediatedTransfer)
    assert app0_events[1].token == token_address
    assert app0_events[1].amount == amount
    assert app0_events[1].hashlock == hashlock
    assert app0_events[1].initiator == app0.raiden.address
    assert app0_events[1].target == app2.raiden.address
    assert app0_events[1].receiver == app3.raiden.address

    #  not checking the identifier
    assert isinstance(app0_events[2], SendRevealSecret)
    assert app0_events[2].secret == secret
    assert app0_events[2].token == token_address
    assert app0_events[2].receiver == app2.raiden.address
    assert app0_events[2].sender == app0.raiden.address

    # not checking the identifier
    assert isinstance(app0_events[3], SendBalanceProof)
    assert app0_events[3].token == token_address
    assert app0_events[3].channel_address == channel_0_3.channel_address
    assert app0_events[3].receiver == app3.raiden.address
    assert app0_events[3].secret == secret

    assert isinstance(app0_events[4], EventTransferSentSuccess)

    # EventUnlockSuccess, not checking the identifier
    assert isinstance(app0_events[5], EventUnlockSuccess)
    assert app0_events[5].hashlock == hashlock

    # app3 is the mediator
    assert isinstance(app3_state_changes[0], ActionInitMediator)
    assert app3_state_changes[0].our_address == app3.raiden.address
    # We should have only 1 available route from mediator to target
    from_route = RouteState(
        state='opened',
        node_address=app0.raiden.address,
        channel_address=channel_0_3.channel_address,
        available_balance=deposit,
        settle_timeout=settle_timeout,
        reveal_timeout=reveal_timeout,
        closed_block=None,
    )
    to_route = RouteState(
        state='opened',
        node_address=app2.raiden.address,
        channel_address=channel_3_2.channel_address,
        available_balance=deposit,
        settle_timeout=settle_timeout,
        reveal_timeout=reveal_timeout,
        closed_block=None,
    )

    assert app3_state_changes[0].from_route == from_route
    assert len(app3_state_changes[0].routes.available_routes) == 1
    assert len(app3_state_changes[0].routes.ignored_routes) == 0
    assert len(app3_state_changes[0].routes.refunded_routes) == 0
    assert len(app3_state_changes[0].routes.canceled_routes) == 0
    assert app3_state_changes[0].routes.available_routes[0] == to_route
    # check the from_transfer is correct
    assert app3_state_changes[0].from_transfer.amount == amount
    assert app3_state_changes[0].from_transfer.hashlock == hashlock
    assert app3_state_changes[0].from_transfer.token == token_address
    assert app3_state_changes[0].from_transfer.initiator == app0.raiden.address
    assert app3_state_changes[0].from_transfer.target == app2.raiden.address

    # The mediator should have also received a SecretReveal from the target
    assert isinstance(app3_state_changes[1], ReceiveSecretReveal)
    assert app3_state_changes[1].sender == app2.raiden.address
    assert app3_state_changes[1].secret == secret

    # If the mediator received any more it is from the initiator
    # TODO: Figure out why we may get two times the secret reveal from the initiator
    for state_change in app3_state_changes[2:]:
        assert isinstance(state_change, ReceiveSecretReveal)
        assert state_change.sender == app0.raiden.address
        assert state_change.secret == secret

    # check app3 state events
    assert len(app3_events) == 4
    assert isinstance(app3_events[0], SendMediatedTransfer)
    assert app3_events[0].token == token_address
    assert app3_events[0].amount == amount
    assert app3_events[0].hashlock == hashlock
    assert app3_events[0].initiator == app0.raiden.address
    assert app3_events[0].target == app2.raiden.address
    assert app3_events[0].receiver == app2.raiden.address

    assert isinstance(app3_events[1], SendRevealSecret)
    assert app3_events[1].secret == secret
    assert app3_events[1].token == token_address
    assert app3_events[1].receiver == app0.raiden.address
    assert app3_events[1].sender == app3.raiden.address

    assert isinstance(app3_events[2], SendBalanceProof)
    assert app3_events[2].token == token_address
    assert app3_events[2].channel_address == channel_3_2.channel_address
    assert app3_events[2].receiver == app2.raiden.address
    assert app3_events[2].secret == secret

    assert isinstance(app3_events[3], EventUnlockSuccess)

    # app2 is the target of the mediated transfer
    assert len(app2_state_changes
               ) == 4  # We get 2 secret reveals from the mediator. WHY?
    assert isinstance(app2_state_changes[0], ActionInitTarget)
    assert app2_state_changes[0].our_address == app2.raiden.address
    # check the route the transfer came from
    from_route = RouteState(
        state='opened',
        node_address=app3.raiden.address,
        channel_address=channel_3_2.channel_address,
        available_balance=deposit,
        settle_timeout=settle_timeout,
        reveal_timeout=reveal_timeout,
        closed_block=None,
    )
    assert app2_state_changes[0].from_route == from_route
    # check the from_transfer is correct
    assert app2_state_changes[0].from_transfer.amount == amount
    assert app2_state_changes[0].from_transfer.hashlock == hashlock
    assert app2_state_changes[0].from_transfer.token == token_address
    assert app2_state_changes[0].from_transfer.initiator == app0.raiden.address
    assert app2_state_changes[0].from_transfer.target == app2.raiden.address

    # We also get secret reveals from the initiator and the mediator.
    assert isinstance(app2_state_changes[1], ReceiveSecretReveal)
    assert app2_state_changes[1].sender == app0.raiden.address
    assert app2_state_changes[1].secret == secret

    # TODO: Figure out why we get two times the Secret Reveal from the mediator
    assert isinstance(app2_state_changes[2], ReceiveSecretReveal)
    assert app2_state_changes[2].sender == app3.raiden.address
    assert app2_state_changes[2].secret == secret
    assert isinstance(app2_state_changes[3], ReceiveSecretReveal)
    assert app2_state_changes[3].sender == app3.raiden.address
    assert app2_state_changes[3].secret == secret

    # check app2 state events
    assert len(app2_events) == 2
    assert isinstance(app2_events[0], SendSecretRequest)
    assert app2_events[0].amount == amount
    assert app2_events[0].hashlock == hashlock
    assert app2_events[0].receiver == app0.raiden.address
    assert isinstance(app2_events[1], SendRevealSecret)
    assert app2_events[1].token == token_address
    assert app2_events[1].secret == secret
    assert app2_events[1].receiver == app3.raiden.address
    assert app2_events[1].sender == app2.raiden.address
Exemplo n.º 20
0
def test_refund_transfer(
    raiden_chain,
    number_of_nodes,
    token_addresses,
    deposit,
    network_wait,
    retry_timeout,
    # UDP does not seem to retry messages until processed
    # https://github.com/raiden-network/raiden/issues/3185
    skip_if_not_matrix,
):
    """A failed transfer must send a refund back.

    TODO:
        - Unlock the token on refund #1091
        - Clear the merkletree and update the locked amount #193
        - Remove the refund message type #490"""
    # Topology:
    #
    #  0 -> 1 -> 2
    #
    app0, app1, app2 = raiden_chain
    token_address = token_addresses[0]
    payment_network_identifier = app0.raiden.default_registry.address
    token_network_identifier = views.get_token_network_identifier_by_token_address(
        views.state_from_app(app0),
        payment_network_identifier,
        token_address,
    )

    # make a transfer to test the path app0 -> app1 -> app2
    identifier_path = 1
    amount_path = 1
    mediated_transfer(
        app0,
        app2,
        token_network_identifier,
        amount_path,
        identifier_path,
        timeout=network_wait * number_of_nodes,
    )

    # drain the channel app1 -> app2
    identifier_drain = 2
    amount_drain = deposit * 8 // 10
    mediated_transfer(
        initiator_app=app1,
        target_app=app2,
        token_network_identifier=token_network_identifier,
        amount=amount_drain,
        identifier=identifier_drain,
        timeout=network_wait,
    )

    # wait for the nodes to sync
    gevent.sleep(0.2)

    assert_synced_channel_state(
        token_network_identifier,
        app0,
        deposit - amount_path,
        [],
        app1,
        deposit + amount_path,
        [],
    )
    assert_synced_channel_state(
        token_network_identifier,
        app1,
        deposit - amount_path - amount_drain,
        [],
        app2,
        deposit + amount_path + amount_drain,
        [],
    )

    # app0 -> app1 -> app2 is the only available path, but the channel app1 ->
    # app2 doesn't have capacity, so a refund will be sent on app1 -> app0
    identifier_refund = 3
    amount_refund = 50
    payment_status = app0.raiden.mediated_transfer_async(
        token_network_identifier,
        amount_refund,
        app2.raiden.address,
        identifier_refund,
    )
    msg = 'there is no path with capacity, the transfer must fail'
    assert payment_status.payment_done.wait() is False, msg

    gevent.sleep(0.2)

    # A lock structure with the correct amount

    send_locked = raiden_events_search_for_item(
        app0.raiden,
        SendLockedTransfer,
        {'transfer': {
            'lock': {
                'amount': amount_refund
            }
        }},
    )
    assert send_locked
    secrethash = send_locked.transfer.lock.secrethash

    send_refund = raiden_events_search_for_item(app1.raiden,
                                                SendRefundTransfer, {})
    assert send_refund

    lock = send_locked.transfer.lock
    refund_lock = send_refund.transfer.lock
    assert lock.amount == refund_lock.amount
    assert lock.secrethash
    assert lock.expiration
    assert lock.secrethash == refund_lock.secrethash

    # Both channels have the amount locked because of the refund message
    assert_synced_channel_state(
        token_network_identifier,
        app0,
        deposit - amount_path,
        [lock],
        app1,
        deposit + amount_path,
        [refund_lock],
    )
    assert_synced_channel_state(
        token_network_identifier,
        app1,
        deposit - amount_path - amount_drain,
        [],
        app2,
        deposit + amount_path + amount_drain,
        [],
    )

    # Additional checks for LockExpired causing nonce mismatch after refund transfer:
    # https://github.com/raiden-network/raiden/issues/3146#issuecomment-447378046
    # At this point make sure that the initiator has not deleted the payment task
    assert secrethash in state_from_raiden(
        app0.raiden).payment_mapping.secrethashes_to_task

    # Wait for lock lock expiration but make sure app0 never processes LockExpired
    with dont_handle_lock_expired_mock(app0):
        wait_for_block(
            raiden=app0.raiden,
            block_number=channel.get_sender_expiration_threshold(lock) + 1,
            retry_timeout=retry_timeout,
        )
        # make sure that app0 still has the payment task for the secrethash
        # https://github.com/raiden-network/raiden/issues/3183
        assert secrethash in state_from_raiden(
            app0.raiden).payment_mapping.secrethashes_to_task

        # make sure that app1 sent a lock expired message for the secrethash
        send_lock_expired = raiden_events_search_for_item(
            app1.raiden,
            SendLockExpired,
            {'secrethash': secrethash},
        )
        assert send_lock_expired
        # make sure that app0 never got it
        state_changes = app0.raiden.wal.storage.get_statechanges_by_identifier(
            0, 'latest')
        assert not search_for_item(
            state_changes,
            ReceiveLockExpired,
            {'secrethash': secrethash},
        )

    # Out of the handicapped app0 transport.
    # Now wait till app0 receives and processes LockExpired
    receive_lock_expired = wait_for_state_change(
        app0.raiden,
        ReceiveLockExpired,
        {'secrethash': secrethash},
        retry_timeout,
    )
    # And also till app1 received the processed
    wait_for_state_change(
        app1.raiden,
        ReceiveProcessed,
        {'message_identifier': receive_lock_expired.message_identifier},
        retry_timeout,
    )

    # make sure app1 queue has cleared the SendLockExpired
    chain_state1 = views.state_from_app(app1)
    queues1 = views.get_all_messagequeues(chain_state=chain_state1)
    result = [(queue_id, queue) for queue_id, queue in queues1.items()
              if queue_id.recipient == app0.raiden.address and queue]
    assert not result

    # and now wait for 1 more block so that the payment task can be deleted
    wait_for_block(
        raiden=app0.raiden,
        block_number=app0.raiden.get_block_number() + 1,
        retry_timeout=retry_timeout,
    )

    # and since the lock expired message has been sent and processed then the
    # payment task should have been deleted from both nodes
    # https://github.com/raiden-network/raiden/issues/3183
    assert secrethash not in state_from_raiden(
        app0.raiden).payment_mapping.secrethashes_to_task
    assert secrethash not in state_from_raiden(
        app1.raiden).payment_mapping.secrethashes_to_task
Exemplo n.º 21
0
def test_recovery_unhappy_case(
        raiden_network,
        number_of_nodes,
        deposit,
        token_addresses,
        network_wait,
        skip_if_not_udp,
        retry_timeout,
):
    app0, app1, app2 = raiden_network
    token_address = token_addresses[0]
    chain_state = views.state_from_app(app0)
    payment_network_id = app0.raiden.default_registry.address
    token_network_identifier = views.get_token_network_identifier_by_token_address(
        chain_state,
        payment_network_id,
        token_address,
    )

    # make a few transfers from app0 to app2
    amount = 1
    spent_amount = deposit - 2
    for _ in range(spent_amount):
        mediated_transfer(
            app0,
            app2,
            token_network_identifier,
            amount,
            timeout=network_wait * number_of_nodes,
        )

    app0.raiden.stop()
    host_port = (app0.raiden.config['host'], app0.raiden.config['port'])
    socket = server._udp_socket(host_port)

    new_transport = UDPTransport(
        app0.discovery,
        socket,
        app0.raiden.transport.throttle_policy,
        app0.raiden.config['transport'],
    )

    app0.stop()

    RaidenAPI(app1.raiden).channel_close(
        app1.raiden.default_registry.address,
        token_address,
        app0.raiden.address,
    )

    channel01 = views.get_channelstate_for(
        views.state_from_app(app1),
        app1.raiden.default_registry.address,
        token_address,
        app0.raiden.address,
    )

    waiting.wait_for_settle(
        app1.raiden,
        app1.raiden.default_registry.address,
        token_address,
        [channel01.identifier],
        retry_timeout,
    )

    app0_restart = App(
        config=app0.config,
        chain=app0.raiden.chain,
        query_start_block=0,
        default_registry=app0.raiden.default_registry,
        default_secret_registry=app0.raiden.default_secret_registry,
        transport=new_transport,
        discovery=app0.raiden.discovery,
    )
    del app0  # from here on the app0_restart should be used

    assert_synched_channel_state(
        token_network_identifier,
        app0_restart, deposit - spent_amount, [],
        app1, deposit + spent_amount, [],
    )
    assert_synched_channel_state(
        token_network_identifier,
        app1, deposit - spent_amount, [],
        app2, deposit + spent_amount, [],
    )
def test_receive_lockedtransfer_invalidnonce(
        raiden_network,
        number_of_nodes,
        deposit,
        token_addresses,
        reveal_timeout,
        network_wait,
):

    app0, app1, app2 = raiden_network
    token_address = token_addresses[0]
    token_network_identifier = views.get_token_network_identifier_by_token_address(
        views.state_from_app(app0),
        app0.raiden.default_registry.address,
        token_address,
    )
    channel0 = get_channelstate(app0, app1, token_network_identifier)

    amount = 10
    mediated_transfer(
        app0,
        app2,
        token_network_identifier,
        amount,
        timeout=network_wait * number_of_nodes,
    )

    amount = 10
    payment_identifier = 1
    repeated_nonce = 1
    expiration = reveal_timeout * 2
    mediated_transfer_message = LockedTransfer(
        chain_id=UNIT_CHAIN_ID,
        message_identifier=random.randint(0, UINT64_MAX),
        payment_identifier=payment_identifier,
        nonce=repeated_nonce,
        token_network_address=token_network_identifier,
        token=token_address,
        channel_identifier=channel0.identifier,
        transferred_amount=amount,
        locked_amount=amount,
        recipient=app1.raiden.address,
        locksroot=UNIT_SECRETHASH,
        lock=Lock(amount, expiration, UNIT_SECRETHASH),
        target=app2.raiden.address,
        initiator=app0.raiden.address,
        fee=0,
    )

    sign_and_inject(
        mediated_transfer_message,
        app0.raiden.private_key,
        app0.raiden.address,
        app1,
    )

    with gevent.Timeout(network_wait):
        wait_assert(
            assert_synced_channel_state,
            token_network_identifier,
            app0, deposit - amount, [],
            app1, deposit + amount, [],
        )
Exemplo n.º 23
0
def test_different_view_of_last_bp_during_unlock(
        raiden_chain,
        number_of_nodes,
        token_addresses,
        deposit,
        network_wait,
        retry_timeout,
        # UDP does not seem to retry messages until processed
        # https://github.com/raiden-network/raiden/issues/3185
        skip_if_not_matrix,
):
    """Test for https://github.com/raiden-network/raiden/issues/3196#issuecomment-449163888"""
    # Topology:
    #
    #  0 -> 1 -> 2
    #
    app0, app1, app2 = raiden_chain
    token_address = token_addresses[0]
    payment_network_identifier = app0.raiden.default_registry.address
    token_network_identifier = views.get_token_network_identifier_by_token_address(
        views.state_from_app(app0),
        payment_network_identifier,
        token_address,
    )
    token_proxy = app0.raiden.chain.token(token_address)
    initial_balance0 = token_proxy.balance_of(app0.raiden.address)
    initial_balance1 = token_proxy.balance_of(app1.raiden.address)

    # make a transfer to test the path app0 -> app1 -> app2
    identifier_path = 1
    amount_path = 1
    mediated_transfer(
        app0,
        app2,
        token_network_identifier,
        amount_path,
        identifier_path,
        timeout=network_wait * number_of_nodes,
    )

    # drain the channel app1 -> app2
    identifier_drain = 2
    amount_drain = deposit * 8 // 10
    mediated_transfer(
        initiator_app=app1,
        target_app=app2,
        token_network_identifier=token_network_identifier,
        amount=amount_drain,
        identifier=identifier_drain,
        timeout=network_wait,
    )

    # wait for the nodes to sync
    gevent.sleep(0.2)

    assert_synced_channel_state(
        token_network_identifier,
        app0, deposit - amount_path, [],
        app1, deposit + amount_path, [],
    )
    assert_synced_channel_state(
        token_network_identifier,
        app1, deposit - amount_path - amount_drain, [],
        app2, deposit + amount_path + amount_drain, [],
    )

    # app0 -> app1 -> app2 is the only available path, but the channel app1 ->
    # app2 doesn't have capacity, so a refund will be sent on app1 -> app0
    identifier_refund = 3
    amount_refund = 50
    async_result = app0.raiden.mediated_transfer_async(
        token_network_identifier,
        amount_refund,
        app2.raiden.address,
        identifier_refund,
    )
    assert async_result.wait() is False, 'there is no path with capacity, the transfer must fail'

    gevent.sleep(0.2)

    # A lock structure with the correct amount

    send_locked = raiden_events_must_contain_entry(
        app0.raiden,
        SendLockedTransfer,
        {'transfer': {'lock': {'amount': amount_refund}}},
    )
    assert send_locked
    secrethash = send_locked.transfer.lock.secrethash

    send_refund = raiden_events_must_contain_entry(app1.raiden, SendRefundTransfer, {})
    assert send_refund

    lock = send_locked.transfer.lock
    refund_lock = send_refund.transfer.lock
    assert lock.amount == refund_lock.amount
    assert lock.secrethash
    assert lock.expiration
    assert lock.secrethash == refund_lock.secrethash

    # Both channels have the amount locked because of the refund message
    assert_synced_channel_state(
        token_network_identifier,
        app0, deposit - amount_path, [lockstate_from_lock(lock)],
        app1, deposit + amount_path, [lockstate_from_lock(refund_lock)],
    )
    assert_synced_channel_state(
        token_network_identifier,
        app1, deposit - amount_path - amount_drain, [],
        app2, deposit + amount_path + amount_drain, [],
    )

    # Additional checks for LockExpired causing nonce mismatch after refund transfer:
    # https://github.com/raiden-network/raiden/issues/3146#issuecomment-447378046
    # At this point make sure that the initiator has not deleted the payment task
    assert secrethash in state_from_raiden(app0.raiden).payment_mapping.secrethashes_to_task

    with dont_handle_node_change_network_state():
        # now app1 goes offline
        app1.raiden.stop()
        app1.raiden.get()
        assert not app1.raiden

        # Wait for lock expiration so that app0 sends a LockExpired
        wait_for_block(
            raiden=app0.raiden,
            block_number=channel.get_sender_expiration_threshold(lock) + 1,
            retry_timeout=retry_timeout,
        )

        # make sure that app0 sent a lock expired message for the secrethash
        wait_for_raiden_event(
            app0.raiden,
            SendLockExpired,
            {'secrethash': secrethash},
            retry_timeout,
        )

        # now app0 closes the channel
        RaidenAPI(app0.raiden).channel_close(
            registry_address=payment_network_identifier,
            token_address=token_address,
            partner_address=app1.raiden.address,
        )

    count = 0
    original_update = app1.raiden.raiden_event_handler.handle_contract_send_channelupdate

    def patched_update(raiden, event):
        nonlocal count
        count += 1
        original_update(raiden, event)

    app1.raiden.raiden_event_handler.handle_contract_send_channelupdate = patched_update
    # and now app1 comes back online
    app1.raiden.start()
    # test for https://github.com/raiden-network/raiden/issues/3216
    assert count == 1, 'Update transfer should have only been called once during restart'
    channel_identifier = get_channelstate(app0, app1, token_network_identifier).identifier

    # and we wait for settlement
    wait_for_settle(
        raiden=app0.raiden,
        payment_network_id=payment_network_identifier,
        token_address=token_address,
        channel_ids=[channel_identifier],
        retry_timeout=app0.raiden.alarm.sleep_time,
    )

    with gevent.Timeout(10):
        unlock_app0 = wait_for_state_change(
            app0.raiden,
            ContractReceiveChannelBatchUnlock,
            {'participant': app0.raiden.address},
            retry_timeout,
        )
    assert unlock_app0.returned_tokens == 50
    with gevent.Timeout(10):
        unlock_app1 = wait_for_state_change(
            app1.raiden,
            ContractReceiveChannelBatchUnlock,
            {'participant': app1.raiden.address},
            retry_timeout,
        )
    assert unlock_app1.returned_tokens == 50
    final_balance0 = token_proxy.balance_of(app0.raiden.address)
    final_balance1 = token_proxy.balance_of(app1.raiden.address)

    assert final_balance0 - deposit - initial_balance0 == -1
    assert final_balance1 - deposit - initial_balance1 == 1
Exemplo n.º 24
0
def test_refund_transfer_after_2nd_hop(
    raiden_chain,
    number_of_nodes,
    token_addresses,
    deposit,
    network_wait,
):
    """Test the refund transfer sent due to failure after 2nd hop"""
    # Topology:
    #
    #  0 -> 1 -> 2 -> 3
    #
    app0, app1, app2, app3 = raiden_chain
    token_address = token_addresses[0]
    payment_network_identifier = app0.raiden.default_registry.address
    token_network_identifier = views.get_token_network_identifier_by_token_address(
        views.state_from_app(app0),
        payment_network_identifier,
        token_address,
    )

    # make a transfer to test the path app0 -> app1 -> app2 -> app3
    identifier_path = 1
    amount_path = 1
    mediated_transfer(
        app0,
        app3,
        token_network_identifier,
        amount_path,
        identifier_path,
        timeout=network_wait * number_of_nodes,
    )

    # drain the channel app2 -> app3
    identifier_drain = 2
    amount_drain = deposit * 8 // 10
    direct_transfer(
        app2,
        app3,
        token_network_identifier,
        amount_drain,
        identifier_drain,
        timeout=network_wait,
    )

    # wait for the nodes to sync
    gevent.sleep(0.2)

    assert_synced_channel_state(
        token_network_identifier,
        app0,
        deposit - amount_path,
        [],
        app1,
        deposit + amount_path,
        [],
    )
    assert_synced_channel_state(
        token_network_identifier,
        app1,
        deposit - amount_path,
        [],
        app2,
        deposit + amount_path,
        [],
    )
    assert_synced_channel_state(
        token_network_identifier,
        app2,
        deposit - amount_path - amount_drain,
        [],
        app3,
        deposit + amount_path + amount_drain,
        [],
    )

    # app0 -> app1 -> app2 > app3 is the only available path, but the channel
    # app2 -> app3 doesn't have capacity, so a refund will be sent on
    # app2 -> app1 -> app0
    identifier_refund = 3
    amount_refund = 50
    async_result = app0.raiden.mediated_transfer_async(
        token_network_identifier,
        amount_refund,
        app3.raiden.address,
        identifier_refund,
    )
    assert async_result.wait(
    ) is False, 'there is no path with capacity, the transfer must fail'

    gevent.sleep(0.2)

    # Lock structures with the correct amount

    send_locked1 = raiden_events_must_contain_entry(
        app0.raiden,
        SendLockedTransfer,
        {'transfer': {
            'lock': {
                'amount': amount_refund
            }
        }},
    )
    assert send_locked1

    send_refund1 = raiden_events_must_contain_entry(app1.raiden,
                                                    SendRefundTransfer, {})
    assert send_refund1

    lock1 = send_locked1.transfer.lock
    refund_lock1 = send_refund1.transfer.lock
    assert lock1.amount == refund_lock1.amount
    assert lock1.secrethash == refund_lock1.secrethash

    send_locked2 = raiden_events_must_contain_entry(
        app1.raiden,
        SendLockedTransfer,
        {'transfer': {
            'lock': {
                'amount': amount_refund
            }
        }},
    )
    assert send_locked2

    send_refund2 = raiden_events_must_contain_entry(app2.raiden,
                                                    SendRefundTransfer, {})
    assert send_refund2

    lock2 = send_locked2.transfer.lock
    refund_lock2 = send_refund2.transfer.lock
    assert lock2.amount == refund_lock2.amount
    assert lock2.secrethash
    assert lock2.expiration

    # channels have the amount locked because of the refund message
    assert_synced_channel_state(
        token_network_identifier,
        app0,
        deposit - amount_path,
        [lockstate_from_lock(lock1)],
        app1,
        deposit + amount_path,
        [lockstate_from_lock(refund_lock1)],
    )
    assert_synced_channel_state(
        token_network_identifier,
        app1,
        deposit - amount_path,
        [lockstate_from_lock(lock2)],
        app2,
        deposit + amount_path,
        [lockstate_from_lock(refund_lock2)],
    )
    assert_synced_channel_state(
        token_network_identifier,
        app2,
        deposit - amount_path - amount_drain,
        [],
        app3,
        deposit + amount_path + amount_drain,
        [],
    )
Exemplo n.º 25
0
def test_mediated_transfer_events(raiden_network, number_of_nodes,
                                  token_addresses, network_wait):
    app0, app1, app2 = raiden_network
    token_address = token_addresses[0]
    chain_state = views.state_from_app(app0)
    payment_network_id = app0.raiden.default_registry.address
    token_network_identifier = views.get_token_network_identifier_by_token_address(
        chain_state,
        payment_network_id,
        token_address,
    )

    amount = 10
    mediated_transfer(
        app0,
        app2,
        token_network_identifier,
        amount,
        timeout=network_wait * number_of_nodes,
    )

    def test_initiator_events():
        initiator_blockevents = app0.raiden.wal.storage.get_events_by_identifier(
            from_identifier=0,
            to_identifier='latest',
        )
        initiator_events = [
            blocknumber_event[1] for blocknumber_event in initiator_blockevents
        ]
        return (must_contain_entry(initiator_events, SendRevealSecret, {}) and
                must_contain_entry(initiator_events, EventUnlockSuccess, {}))

    assert wait_until(test_initiator_events, network_wait)

    def test_mediator_events():
        mediator_blockevents = app1.raiden.wal.storage.get_events_by_identifier(
            from_identifier=0,
            to_identifier='latest',
        )
        mediator_events = [
            blocknumber_event[1] for blocknumber_event in mediator_blockevents
        ]
        return (must_contain_entry(mediator_events, EventUnlockSuccess, {})
                and must_contain_entry(mediator_events,
                                       EventUnlockClaimSuccess, {}))

    assert wait_until(test_mediator_events, network_wait)

    def test_target_events():
        target_blockevents = app2.raiden.wal.storage.get_events_by_identifier(
            from_identifier=0,
            to_identifier='latest',
        )
        target_events = [
            blocknumber_event[1] for blocknumber_event in target_blockevents
        ]
        return (must_contain_entry(target_events, SendSecretRequest, {})
                and must_contain_entry(target_events, SendRevealSecret, {}) and
                must_contain_entry(target_events, EventUnlockClaimSuccess, {}))

    assert wait_until(test_target_events, network_wait)
Exemplo n.º 26
0
def test_settled_lock(token_addresses, raiden_network, deposit):
    """ Any transfer following a secret reveal must update the locksroot, so
    that an attacker cannot reuse a secret to double claim a lock.
    """
    app0, app1 = raiden_network
    registry_address = app0.raiden.default_registry.address
    token_address = token_addresses[0]
    amount = 30
    token_network_identifier = views.get_token_network_identifier_by_token_address(
        views.state_from_app(app0),
        app0.raiden.default_registry.address,
        token_address,
    )

    hold_event_handler = HoldOffChainSecretRequest()
    app1.raiden.raiden_event_handler = hold_event_handler

    address0 = app0.raiden.address
    address1 = app1.raiden.address

    deposit0 = deposit
    deposit1 = deposit

    token_proxy = app0.raiden.chain.token(token_address)
    initial_balance0 = token_proxy.balance_of(address0)
    initial_balance1 = token_proxy.balance_of(address1)
    identifier = 1
    target = app1.raiden.address
    secret = sha3(target)
    secrethash = sha3(secret)

    secret_available = hold_event_handler.hold_secretrequest_for(
        secrethash=secrethash)

    app0.raiden.start_mediated_transfer_with_secret(
        token_network_identifier,
        amount,
        target,
        identifier,
        secret,
    )

    secret_available.wait()  # wait for the messages to be exchanged

    # Save the merkle tree leaves from the pending transfer, used to test the unlock
    channelstate_0_1 = get_channelstate(app0, app1, token_network_identifier)
    batch_unlock = channel.get_batch_unlock(channelstate_0_1.our_state)
    assert batch_unlock

    hold_event_handler.release_secretrequest_for(
        app1.raiden,
        secrethash,
    )

    mediated_transfer(
        initiator_app=app0,
        target_app=app1,
        token_network_identifier=token_network_identifier,
        amount=amount,
        identifier=2,
    )

    RaidenAPI(app1.raiden).channel_close(
        registry_address,
        token_address,
        app0.raiden.address,
    )

    waiting.wait_for_settle(
        app1.raiden,
        app1.raiden.default_registry.address,
        token_address,
        [channelstate_0_1.identifier],
        app1.raiden.alarm.sleep_time,
    )

    netting_channel = app1.raiden.chain.payment_channel(
        token_network_identifier,
        channelstate_0_1.identifier,
    )

    # The transfer locksroot must not contain the unlocked lock, the
    # unlock must fail.
    with pytest.raises(Exception):
        netting_channel.unlock(
            channelstate_0_1.partner_state.address,
            batch_unlock,
        )

    expected_balance0 = initial_balance0 + deposit0 - amount * 2
    expected_balance1 = initial_balance1 + deposit1 + amount * 2

    assert token_proxy.balance_of(address0) == expected_balance0
    assert token_proxy.balance_of(address1) == expected_balance1
Exemplo n.º 27
0
def test_automatic_dispute(raiden_network, deposit, token_addresses):
    app0, app1 = raiden_network
    registry_address = app0.raiden.default_registry.address
    token_address = token_addresses[0]
    token_network_identifier = views.get_token_network_identifier_by_token_address(
        views.state_from_app(app0),
        app0.raiden.default_registry.address,
        token_address,
    )

    channel0 = get_channelstate(app0, app1, token_network_identifier)
    token_proxy = app0.raiden.chain.token(channel0.token_address)
    initial_balance0 = token_proxy.balance_of(app0.raiden.address)
    initial_balance1 = token_proxy.balance_of(app1.raiden.address)

    amount0_1 = 10
    mediated_transfer(
        initiator_app=app0,
        target_app=app1,
        token_network_identifier=token_network_identifier,
        amount=amount0_1,
    )

    amount1_1 = 50
    mediated_transfer(
        initiator_app=app1,
        target_app=app0,
        token_network_identifier=token_network_identifier,
        amount=amount1_1,
    )

    amount0_2 = 60
    mediated_transfer(
        initiator_app=app0,
        target_app=app1,
        token_network_identifier=token_network_identifier,
        amount=amount0_2,
    )

    # Alice can only provide one of Bob's transfer, so she is incentivized to
    # use the one with the largest transferred_amount.
    RaidenAPI(app0.raiden).channel_close(
        registry_address,
        token_address,
        app1.raiden.address,
    )

    # Bob needs to provide a transfer otherwise its netted balance will be
    # wrong, so he is incentivised to use Alice's transfer with the largest
    # transferred_amount.
    #
    # This is done automatically
    # channel1.external_state.update_transfer(
    #     alice_second_transfer,
    # )

    waiting.wait_for_settle(
        app0.raiden,
        registry_address,
        token_address,
        [channel0.identifier],
        app0.raiden.alarm.sleep_time,
    )

    # check that the channel is properly settled and that Bob's client
    # automatically called updateTransfer() to reflect the actual transactions
    assert token_proxy.balance_of(token_network_identifier) == 0
    total0 = amount0_1 + amount0_2
    total1 = amount1_1
    expected_balance0 = initial_balance0 + deposit - total0 + total1
    expected_balance1 = initial_balance1 + deposit + total0 - total1
    assert token_proxy.balance_of(app0.raiden.address) == expected_balance0
    assert token_proxy.balance_of(app1.raiden.address) == expected_balance1
Exemplo n.º 28
0
def test_node_can_settle_if_partner_does_not_call_update_transfer(
        raiden_network,
        number_of_nodes,
        deposit,
        token_addresses,
        network_wait,
        chain_id,
):
    """ A node must be able to settle a channel, even if the partner did not
    call update transfer.

    This test will:
    - Make a transfer from app0 to app1, to make sure there are balance
    proofs available
    - Stop app1, to make sure update is not called.
    - Use app0 to close the channel.
    - Assert that app0 can settle the closed channel, even though app1 didn't
    use the latest balance proof
    """

    app0, app1 = raiden_network
    token_address = token_addresses[0]
    chain_state = views.state_from_app(app0)
    payment_network_id = app0.raiden.default_registry.address
    registry_address = app0.raiden.default_registry.address
    token_network_identifier = views.get_token_network_identifier_by_token_address(
        chain_state=chain_state,
        payment_network_id=payment_network_id,
        token_address=token_address,
    )
    channel_identifier = get_channelstate(app0, app1, token_network_identifier).identifier

    mediated_transfer(
        initiator_app=app0,
        target_app=app1,
        token_network_identifier=token_network_identifier,
        amount=1,
        timeout=network_wait * number_of_nodes,
    )
    # stop app1 - the test uses token_network_contract now
    app1.stop()
    RaidenAPI(app0.raiden).channel_close(
        registry_address=registry_address,
        token_address=token_address,
        partner_address=app1.raiden.address,
    )
    waiting.wait_for_close(
        raiden=app0.raiden,
        payment_network_id=registry_address,
        token_address=token_address,
        channel_ids=[channel_identifier],
        retry_timeout=app0.raiden.alarm.sleep_time,
    )

    # app1 won't update the channel

    waiting.wait_for_settle(
        raiden=app0.raiden,
        payment_network_id=registry_address,
        token_address=token_address,
        channel_ids=[channel_identifier],
        retry_timeout=app0.raiden.alarm.sleep_time,
    )
    state_changes = app0.raiden.wal.storage.get_statechanges_by_identifier(
        from_identifier=0,
        to_identifier='latest',
    )
    assert must_contain_entry(state_changes, ContractReceiveChannelSettled, {
        'token_network_identifier': token_network_identifier,
        'channel_identifier': channel_identifier,
    })
def test_node_can_settle_if_close_didnt_use_any_balance_proof(
    raiden_network,
    number_of_nodes,
    deposit,
    token_addresses,
    network_wait,
):
    """ A node must be able to settle a channel, even if the partner used an
    old balance proof to close it.

    This test will:
    - Make a transfer from app0 to app1, to make sure there are balance
    proofs available
    - Call close manually in behalf of app1, without any balance proof data
    - Assert that app0 can settle the closed channel, even though app1 didn't
    use the latest balance proof
    """

    app0, app1 = raiden_network
    token_address = token_addresses[0]
    chain_state = views.state_from_app(app0)
    payment_network_id = app0.raiden.default_registry.address
    registry_address = app0.raiden.default_registry.address
    token_network_identifier = views.get_token_network_identifier_by_token_address(
        chain_state=chain_state,
        payment_network_id=payment_network_id,
        token_address=token_address,
    )
    channel_identifier = get_channelstate(app0, app1,
                                          token_network_identifier).identifier

    # make a transfer from app0 to app1 so that app1 is supposed to have a non
    # empty balance hash
    mediated_transfer(
        initiator_app=app0,
        target_app=app1,
        token_network_identifier=token_network_identifier,
        amount=1,
        timeout=network_wait * number_of_nodes,
    )
    # stop app1 - the test uses token_network_contract now
    app1.stop()
    token_network_contract = TokenNetwork(
        jsonrpc_client=app1.raiden.chain.client,
        token_network_address=token_network_identifier,
        contract_manager=app1.raiden.contract_manager,
    )

    # app1 closes the channel with an empty hash instead of the expected hash
    # of the transferred amount from app0
    token_network_contract.close(
        channel_identifier=channel_identifier,
        partner=app0.raiden.address,
        balance_hash=EMPTY_HASH,
        nonce=0,
        additional_hash=EMPTY_HASH,
        signature=EMPTY_SIGNATURE,
    )
    waiting.wait_for_close(
        raiden=app0.raiden,
        payment_network_id=registry_address,
        token_address=token_address,
        channel_ids=[channel_identifier],
        retry_timeout=app0.raiden.alarm.sleep_time,
    )
    waiting.wait_for_settle(
        raiden=app0.raiden,
        payment_network_id=registry_address,
        token_address=token_address,
        channel_ids=[channel_identifier],
        retry_timeout=app0.raiden.alarm.sleep_time,
    )
    state_changes = app0.raiden.wal.storage.get_statechanges_by_identifier(
        from_identifier=0,
        to_identifier='latest',
    )
    assert search_for_item(
        state_changes, ContractReceiveChannelSettled, {
            'token_network_identifier': token_network_identifier,
            'channel_identifier': channel_identifier,
        })
Exemplo n.º 30
0
def test_settled_lock(token_addresses, raiden_network, deposit):
    """ Any transfer following a secret reveal must update the locksroot, so
    that an attacker cannot reuse a secret to double claim a lock.
    """
    app0, app1 = raiden_network
    registry_address = app0.raiden.default_registry.address
    token_address = token_addresses[0]
    amount = 30
    token_network_identifier = views.get_token_network_identifier_by_token_address(
        views.state_from_app(app0),
        app0.raiden.default_registry.address,
        token_address,
    )

    hold_event_handler = HoldOffChainSecretRequest()
    app1.raiden.raiden_event_handler = hold_event_handler

    address0 = app0.raiden.address
    address1 = app1.raiden.address

    deposit0 = deposit
    deposit1 = deposit

    token_proxy = app0.raiden.chain.token(token_address)
    initial_balance0 = token_proxy.balance_of(address0)
    initial_balance1 = token_proxy.balance_of(address1)
    identifier = 1
    target = app1.raiden.address
    secret = sha3(target)
    secrethash = sha3(secret)

    secret_available = hold_event_handler.hold_secretrequest_for(secrethash=secrethash)

    app0.raiden.start_mediated_transfer_with_secret(
        token_network_identifier,
        amount,
        target,
        identifier,
        secret,
    )

    secret_available.wait()  # wait for the messages to be exchanged

    # Save the merkle tree leaves from the pending transfer, used to test the unlock
    channelstate_0_1 = get_channelstate(app0, app1, token_network_identifier)
    batch_unlock = channel.get_batch_unlock(channelstate_0_1.our_state)
    assert batch_unlock

    hold_event_handler.release_secretrequest_for(
        app1.raiden,
        secrethash,
    )

    mediated_transfer(
        initiator_app=app0,
        target_app=app1,
        token_network_identifier=token_network_identifier,
        amount=amount,
        identifier=2,
    )

    RaidenAPI(app1.raiden).channel_close(
        registry_address,
        token_address,
        app0.raiden.address,
    )

    waiting.wait_for_settle(
        app1.raiden,
        app1.raiden.default_registry.address,
        token_address,
        [channelstate_0_1.identifier],
        app1.raiden.alarm.sleep_time,
    )

    netting_channel = app1.raiden.chain.payment_channel(
        token_network_identifier,
        channelstate_0_1.identifier,
    )

    # The transfer locksroot must not contain the unlocked lock, the
    # unlock must fail.
    with pytest.raises(Exception):
        netting_channel.unlock(
            channelstate_0_1.partner_state.address,
            batch_unlock,
        )

    expected_balance0 = initial_balance0 + deposit0 - amount * 2
    expected_balance1 = initial_balance1 + deposit1 + amount * 2

    assert token_proxy.balance_of(address0) == expected_balance0
    assert token_proxy.balance_of(address1) == expected_balance1
Exemplo n.º 31
0
def test_refund_transfer_after_2nd_hop(
        raiden_chain,
        number_of_nodes,
        token_addresses,
        deposit,
        network_wait,
):
    """Test the refund transfer sent due to failure after 2nd hop"""
    # Topology:
    #
    #  0 -> 1 -> 2 -> 3
    #
    app0, app1, app2, app3 = raiden_chain
    token_address = token_addresses[0]
    payment_network_identifier = app0.raiden.default_registry.address
    token_network_identifier = views.get_token_network_identifier_by_token_address(
        views.state_from_app(app0),
        payment_network_identifier,
        token_address,
    )

    # make a transfer to test the path app0 -> app1 -> app2 -> app3
    identifier_path = 1
    amount_path = 1
    mediated_transfer(
        initiator_app=app0,
        target_app=app3,
        token_network_identifier=token_network_identifier,
        amount=amount_path,
        identifier=identifier_path,
        timeout=network_wait * number_of_nodes,
    )

    # drain the channel app2 -> app3
    identifier_drain = 2
    amount_drain = deposit * 8 // 10
    mediated_transfer(
        initiator_app=app2,
        target_app=app3,
        token_network_identifier=token_network_identifier,
        amount=amount_drain,
        identifier=identifier_drain,
        timeout=network_wait,
    )

    # wait for the nodes to sync
    gevent.sleep(0.2)

    assert_synced_channel_state(
        token_network_identifier,
        app0, deposit - amount_path, [],
        app1, deposit + amount_path, [],
    )
    assert_synced_channel_state(
        token_network_identifier,
        app1, deposit - amount_path, [],
        app2, deposit + amount_path, [],
    )
    assert_synced_channel_state(
        token_network_identifier,
        app2, deposit - amount_path - amount_drain, [],
        app3, deposit + amount_path + amount_drain, [],
    )

    # app0 -> app1 -> app2 > app3 is the only available path, but the channel
    # app2 -> app3 doesn't have capacity, so a refund will be sent on
    # app2 -> app1 -> app0
    identifier_refund = 3
    amount_refund = 50
    async_result = app0.raiden.mediated_transfer_async(
        token_network_identifier,
        amount_refund,
        app3.raiden.address,
        identifier_refund,
    )
    assert async_result.wait() is False, 'there is no path with capacity, the transfer must fail'

    gevent.sleep(0.2)

    # Lock structures with the correct amount

    send_locked1 = raiden_events_must_contain_entry(
        app0.raiden,
        SendLockedTransfer,
        {'transfer': {'lock': {'amount': amount_refund}}},
    )
    assert send_locked1

    send_refund1 = raiden_events_must_contain_entry(app1.raiden, SendRefundTransfer, {})
    assert send_refund1

    lock1 = send_locked1.transfer.lock
    refund_lock1 = send_refund1.transfer.lock
    assert lock1.amount == refund_lock1.amount
    assert lock1.secrethash == refund_lock1.secrethash

    send_locked2 = raiden_events_must_contain_entry(
        app1.raiden,
        SendLockedTransfer,
        {'transfer': {'lock': {'amount': amount_refund}}},
    )
    assert send_locked2

    send_refund2 = raiden_events_must_contain_entry(app2.raiden, SendRefundTransfer, {})
    assert send_refund2

    lock2 = send_locked2.transfer.lock
    refund_lock2 = send_refund2.transfer.lock
    assert lock2.amount == refund_lock2.amount
    assert lock2.secrethash
    assert lock2.expiration

    # channels have the amount locked because of the refund message
    assert_synced_channel_state(
        token_network_identifier,
        app0, deposit - amount_path, [lockstate_from_lock(lock1)],
        app1, deposit + amount_path, [lockstate_from_lock(refund_lock1)],
    )
    assert_synced_channel_state(
        token_network_identifier,
        app1, deposit - amount_path, [lockstate_from_lock(lock2)],
        app2, deposit + amount_path, [lockstate_from_lock(refund_lock2)],
    )
    assert_synced_channel_state(
        token_network_identifier,
        app2, deposit - amount_path - amount_drain, [],
        app3, deposit + amount_path + amount_drain, [],
    )
Exemplo n.º 32
0
def test_fullnetwork(raiden_chain, token_addresses, deposit, settle_timeout,
                     reveal_timeout):
    # pylint: disable=too-many-locals,too-many-statements

    # The network has the following topology:
    #
    #   App0 <---> App1
    #    ^          ^
    #    |          |
    #    v          v
    #   App3 <---> App2

    token_address = token_addresses[0]

    app0, app1, app2, app3 = raiden_chain  # pylint: disable=unbalanced-tuple-unpacking
    channel_0_1 = channel(app0, app1, token_address)
    channel_3_2 = channel(app3, app2, token_address)
    channel_0_3 = channel(app0, app3, token_address)

    # Exhaust the channel deposit (to force the mediated transfer to go backwards)
    amount = deposit
    direct_transfer(app0, app1, token_address, amount, identifier=1)
    assert get_sent_transfer(channel_0_1, 0).transferred_amount == amount

    amount = int(deposit / 2.)
    mediated_transfer(app0, app2, token_address, amount)

    gevent.sleep(0.5)

    # This is the only possible path, the transfer must go backwards
    assert_path_mediated_transfer(
        get_sent_transfer(channel_0_3, 0),
        get_sent_transfer(channel_3_2, 0),
    )

    app0_state_changes = [
        change[1]
        for change in get_all_state_changes(app0.raiden.transaction_log)
    ]

    app0_events = [
        event.event_object
        for event in get_all_state_events(app0.raiden.transaction_log)
    ]

    secret = None
    for event in app0_events:
        if isinstance(event, SendRevealSecret):
            secret = event.secret

    assert secret is not None
    hashlock = sha3(secret)

    # app0 initiates the direct transfer and mediated_transfer
    assert must_contain_entry(
        app0_state_changes, ActionInitInitiator, {
            'our_address': app0.raiden.address,
            'transfer': {
                'amount': amount,
                'token': token_address,
                'initiator': app0.raiden.address,
                'target': app2.raiden.address,
                'expiration': None,
                'hashlock': None,
                'secret': None,
            }
        })

    # Of these 2 the state machine will in the future choose the one with the most
    # available balance
    not_taken_route = RouteState(
        state='opened',
        node_address=app1.raiden.address,
        channel_address=channel_0_1.channel_address,
        available_balance=deposit,
        settle_timeout=settle_timeout,
        reveal_timeout=reveal_timeout,
        closed_block=None,
    )

    taken_route = RouteState(
        state='opened',
        node_address=app3.raiden.address,
        channel_address=channel_0_3.channel_address,
        available_balance=deposit,
        settle_timeout=settle_timeout,
        reveal_timeout=reveal_timeout,
        closed_block=None,
    )

    for state_change in app0_state_changes:
        if isinstance(state_change, ActionInitMediator):
            assert taken_route in state_change.routes.available_routes
            assert not_taken_route not in state_change.routes.available_routes

    # app1 received one direct transfers
    app1_state_changes = [
        change[1]
        for change in get_all_state_changes(app1.raiden.transaction_log)
    ]
    assert must_contain_entry(app1_state_changes, ReceiveBalanceProof, {})
    assert must_contain_entry(app1_state_changes, ReceiveTransferDirect, {})

    app2_state_changes = [
        change[1]
        for change in get_all_state_changes(app2.raiden.transaction_log)
    ]

    assert must_contain_entry(
        app2_state_changes, ActionInitTarget, {
            'our_address': app2.raiden.address,
            'from_route': {
                'state': 'opened',
                'node_address': app3.raiden.address,
                'channel_address': channel_3_2.channel_address,
                'available_balance': deposit,
                'settle_timeout': settle_timeout,
                'reveal_timeout': reveal_timeout,
                'closed_block': None
            },
            'from_transfer': {
                'amount': amount,
                'hashlock': hashlock,
                'token': token_address,
                'initiator': app0.raiden.address,
                'target': app2.raiden.address,
            }
        })

    assert must_contain_entry(app2_state_changes, ReceiveSecretReveal, {
        'sender': app0.raiden.address,
        'secret': secret,
    })

    assert must_contain_entry(app2_state_changes, ReceiveSecretReveal, {
        'sender': app3.raiden.address,
        'secret': secret,
    })

    app2_events = [
        event.event_object
        for event in get_all_state_events(app2.raiden.transaction_log)
    ]

    assert must_contain_entry(app2_events, SendSecretRequest, {
        'amount': amount,
        'hashlock': hashlock,
        'receiver': app0.raiden.address,
    })

    assert must_contain_entry(
        app2_events, SendRevealSecret, {
            'token': token_address,
            'secret': secret,
            'receiver': app3.raiden.address,
            'sender': app2.raiden.address,
        })

    assert must_contain_entry(app0_state_changes, ReceiveSecretRequest, {
        'amount': amount,
        'sender': app2.raiden.address,
        'hashlock': hashlock,
    })

    assert must_contain_entry(app0_state_changes, ReceiveSecretReveal, {
        'sender': app3.raiden.address,
        'secret': secret,
    })

    assert must_contain_entry(app0_events, EventTransferSentSuccess, {})

    assert must_contain_entry(
        app0_events, SendMediatedTransfer, {
            'token': token_address,
            'amount': amount,
            'hashlock': hashlock,
            'initiator': app0.raiden.address,
            'target': app2.raiden.address,
            'receiver': app3.raiden.address,
        })

    assert must_contain_entry(
        app0_events, SendRevealSecret, {
            'secret': secret,
            'token': token_address,
            'receiver': app2.raiden.address,
            'sender': app0.raiden.address,
        })

    assert must_contain_entry(
        app0_events, SendBalanceProof, {
            'token': token_address,
            'channel_address': channel_0_3.channel_address,
            'receiver': app3.raiden.address,
            'secret': secret,
        })

    assert must_contain_entry(app0_events, EventTransferSentSuccess, {})
    assert must_contain_entry(app0_events, EventUnlockSuccess, {
        'hashlock': hashlock,
    })

    app3_state_changes = [
        change[1]
        for change in get_all_state_changes(app3.raiden.transaction_log)
    ]

    assert must_contain_entry(
        app3_state_changes, ActionInitMediator, {
            'our_address': app3.raiden.address,
            'from_route': {
                'state': 'opened',
                'node_address': app0.raiden.address,
                'channel_address': channel_0_3.channel_address,
                'available_balance': deposit,
                'settle_timeout': settle_timeout,
                'reveal_timeout': reveal_timeout,
                'closed_block': None,
            },
            'from_transfer': {
                'amount': amount,
                'hashlock': hashlock,
                'token': token_address,
                'initiator': app0.raiden.address,
                'target': app2.raiden.address,
            }
        })

    assert must_contain_entry(app3_state_changes, ReceiveSecretReveal, {
        'sender': app2.raiden.address,
        'secret': secret,
    })

    assert must_contain_entry(app3_state_changes, ReceiveSecretReveal, {
        'sender': app2.raiden.address,
        'secret': secret,
    })

    app3_events = [
        event.event_object
        for event in get_all_state_events(app3.raiden.transaction_log)
    ]

    assert must_contain_entry(
        app3_events, SendMediatedTransfer, {
            'token': token_address,
            'amount': amount,
            'hashlock': hashlock,
            'initiator': app0.raiden.address,
            'target': app2.raiden.address,
            'receiver': app2.raiden.address,
        })

    assert must_contain_entry(
        app3_events, SendRevealSecret, {
            'secret': secret,
            'token': token_address,
            'receiver': app0.raiden.address,
            'sender': app3.raiden.address,
        })

    assert must_contain_entry(
        app3_events, SendBalanceProof, {
            'token': token_address,
            'channel_address': channel_3_2.channel_address,
            'receiver': app2.raiden.address,
            'secret': secret,
        })
    assert must_contain_entry(app3_events, EventUnlockSuccess, {})
Exemplo n.º 33
0
def test_recovery_unhappy_case(
        raiden_network,
        number_of_nodes,
        deposit,
        token_addresses,
        network_wait,
        skip_if_not_udp,
        retry_timeout,
):
    app0, app1, app2 = raiden_network
    token_address = token_addresses[0]
    chain_state = views.state_from_app(app0)
    payment_network_id = app0.raiden.default_registry.address
    token_network_identifier = views.get_token_network_identifier_by_token_address(
        chain_state,
        payment_network_id,
        token_address,
    )

    # make a few transfers from app0 to app2
    amount = 1
    spent_amount = deposit - 2
    for _ in range(spent_amount):
        mediated_transfer(
            app0,
            app2,
            token_network_identifier,
            amount,
            timeout=network_wait * number_of_nodes,
        )

    app0.raiden.stop()
    host_port = (
        app0.raiden.config['transport']['udp']['host'],
        app0.raiden.config['transport']['udp']['port'],
    )
    socket = server._udp_socket(host_port)

    new_transport = UDPTransport(
        app0.raiden.address,
        app0.discovery,
        socket,
        app0.raiden.transport.throttle_policy,
        app0.raiden.config['transport']['udp'],
    )

    app0.stop()

    RaidenAPI(app1.raiden).channel_close(
        app1.raiden.default_registry.address,
        token_address,
        app0.raiden.address,
    )

    channel01 = views.get_channelstate_for(
        views.state_from_app(app1),
        app1.raiden.default_registry.address,
        token_address,
        app0.raiden.address,
    )

    waiting.wait_for_settle(
        app1.raiden,
        app1.raiden.default_registry.address,
        token_address,
        [channel01.identifier],
        retry_timeout,
    )

    raiden_event_handler = RaidenEventHandler()
    message_handler = MessageHandler()

    app0_restart = App(
        config=app0.config,
        chain=app0.raiden.chain,
        query_start_block=0,
        default_registry=app0.raiden.default_registry,
        default_secret_registry=app0.raiden.default_secret_registry,
        transport=new_transport,
        raiden_event_handler=raiden_event_handler,
        message_handler=message_handler,
        discovery=app0.raiden.discovery,
    )
    del app0  # from here on the app0_restart should be used
    app0_restart.start()

    state_changes = app0_restart.raiden.wal.storage.get_statechanges_by_identifier(
        from_identifier=0,
        to_identifier='latest',
    )

    assert must_contain_entry(state_changes, ContractReceiveChannelSettled, {
        'token_network_identifier': token_network_identifier,
        'channel_identifier': channel01.identifier,
    })
Exemplo n.º 34
0
def test_refund_transfer(raiden_chain, token_addresses, deposit, network_wait):
    """A failed transfer must send a refund back.

    TODO:
        - Unlock the token on refund #1091
        - Clear the merkletree and update the locked amount #193
        - Remove the refund message type #490"""
    # Topology:
    #
    #  0 -> 1 -> 2
    #
    app0, app1, app2 = raiden_chain
    token_address = token_addresses[0]
    payment_network_identifier = app0.raiden.default_registry.address
    token_network_identifier = views.get_token_network_identifier_by_token_address(
        views.state_from_app(app0),
        payment_network_identifier,
        token_address,
    )

    # make a transfer to test the path app0 -> app1 -> app2
    identifier_path = 1
    amount_path = 1
    mediated_transfer(
        app0,
        app2,
        token_network_identifier,
        amount_path,
        identifier_path,
        timeout=network_wait,
    )

    # drain the channel app1 -> app2
    identifier_drain = 2
    amount_drain = deposit * 8 // 10
    direct_transfer(
        app1,
        app2,
        token_network_identifier,
        amount_drain,
        identifier_drain,
        timeout=network_wait,
    )

    # wait for the nodes to sync
    gevent.sleep(0.2)

    assert_synched_channel_state(
        token_network_identifier,
        app0, deposit - amount_path, [],
        app1, deposit + amount_path, [],
    )
    assert_synched_channel_state(
        token_network_identifier,
        app1, deposit - amount_path - amount_drain, [],
        app2, deposit + amount_path + amount_drain, [],
    )

    # app0 -> app1 -> app2 is the only available path, but the channel app1 ->
    # app2 doesn't have capacity, so a refund will be sent on app1 -> app0
    identifier_refund = 3
    amount_refund = 50
    async_result = app0.raiden.mediated_transfer_async(
        token_network_identifier,
        amount_refund,
        app2.raiden.address,
        identifier_refund,
    )
    assert async_result.wait() is False, 'there is no path with capacity, the transfer must fail'

    gevent.sleep(0.2)

    # A lock structure with the correct amount

    send_locked = next(
        event
        for _, event in app0.raiden.wal.storage.get_events_by_identifier(0, 'latest')
        if isinstance(event, SendLockedTransfer) and event.transfer.lock.amount == amount_refund
    )
    assert send_locked

    send_refund = next(
        event
        for _, event in app1.raiden.wal.storage.get_events_by_identifier(0, 'latest')
        if isinstance(event, SendRefundTransfer)
    )
    assert send_refund

    lock = send_locked.transfer.lock
    refund_lock = send_refund.lock
    assert lock.amount == refund_lock.amount
    assert lock.secrethash
    assert lock.expiration

    # Both channels have the amount locked because of the refund message
    assert_synched_channel_state(
        token_network_identifier,
        app0, deposit - amount_path, [lockstate_from_lock(lock)],
        app1, deposit + amount_path, [lockstate_from_lock(refund_lock)],
    )
    assert_synched_channel_state(
        token_network_identifier,
        app1, deposit - amount_path - amount_drain, [],
        app2, deposit + amount_path + amount_drain, [],
    )
Exemplo n.º 35
0
def test_invalid_update_transfer(
        raiden_network,
        number_of_nodes,
        deposit,
        token_addresses,
        network_wait,
        chain_id,
):
    app0, app1 = raiden_network
    token_address = token_addresses[0]
    chain_state = views.state_from_app(app0)
    payment_network_id = app0.raiden.default_registry.address
    registry_address = app0.raiden.default_registry.address
    token_network_identifier = views.get_token_network_identifier_by_token_address(
        chain_state=chain_state,
        payment_network_id=payment_network_id,
        token_address=token_address,
    )
    channel_identifier = get_channelstate(app0, app1, token_network_identifier).identifier

    # make a transfer
    mediated_transfer(
        initiator_app=app0,
        target_app=app1,
        token_network_identifier=token_network_identifier,
        amount=1,
        timeout=network_wait * number_of_nodes,
    )
    # stop app1 - the test uses token_network_contract now
    app1.stop()
    # close the channel
    RaidenAPI(app0.raiden).channel_close(
        registry_address=registry_address,
        token_address=token_address,
        partner_address=app1.raiden.address,
    )
    waiting.wait_for_close(
        raiden=app0.raiden,
        payment_network_id=registry_address,
        token_address=token_address,
        channel_ids=[channel_identifier],
        retry_timeout=app0.raiden.alarm.sleep_time,
    )

    # app1 won't update the channel

    # app0 waits for settle
    waiting.wait_for_settle(
        raiden=app0.raiden,
        payment_network_id=registry_address,
        token_address=token_address,
        channel_ids=[channel_identifier],
        retry_timeout=app0.raiden.alarm.sleep_time,
    )
    state_changes = app0.raiden.wal.storage.get_statechanges_by_identifier(
        from_identifier=0,
        to_identifier='latest',
    )
    assert must_contain_entry(state_changes, ContractReceiveChannelSettled, {
        'token_network_identifier': token_network_identifier,
        'channel_identifier': channel_identifier,
    })
Exemplo n.º 36
0
def test_recovery_happy_case(
        raiden_network,
        number_of_nodes,
        deposit,
        token_addresses,
        network_wait,
        skip_if_not_udp,
):
    app0, app1, app2 = raiden_network
    token_address = token_addresses[0]
    chain_state = views.state_from_app(app0)
    payment_network_id = app0.raiden.default_registry.address
    token_network_identifier = views.get_token_network_identifier_by_token_address(
        chain_state,
        payment_network_id,
        token_address,
    )

    # make a few transfers from app0 to app2
    amount = 1
    spent_amount = deposit - 2
    for _ in range(spent_amount):
        mediated_transfer(
            app0,
            app2,
            token_network_identifier,
            amount,
            timeout=network_wait * number_of_nodes,
        )

    app0.raiden.stop()
    host_port = (
        app0.raiden.config['transport']['udp']['host'],
        app0.raiden.config['transport']['udp']['port'],
    )
    socket = server._udp_socket(host_port)

    new_transport = UDPTransport(
        app0.raiden.address,
        app0.discovery,
        socket,
        app0.raiden.transport.throttle_policy,
        app0.raiden.config['transport']['udp'],
    )

    raiden_event_handler = RaidenEventHandler()
    message_handler = MessageHandler()

    app0_restart = App(
        config=app0.config,
        chain=app0.raiden.chain,
        query_start_block=0,
        default_registry=app0.raiden.default_registry,
        default_secret_registry=app0.raiden.default_secret_registry,
        transport=new_transport,
        raiden_event_handler=raiden_event_handler,
        message_handler=message_handler,
        discovery=app0.raiden.discovery,
    )

    app0.stop()
    del app0  # from here on the app0_restart should be used

    app0_restart.start()

    assert_synced_channel_state(
        token_network_identifier,
        app0_restart, deposit - spent_amount, [],
        app1, deposit + spent_amount, [],
    )
    assert_synced_channel_state(
        token_network_identifier,
        app1, deposit - spent_amount, [],
        app2, deposit + spent_amount, [],
    )

    # wait for the nodes' healthcheck to update the network statuses
    waiting.wait_for_healthy(
        app0_restart.raiden,
        app1.raiden.address,
        network_wait,
    )
    waiting.wait_for_healthy(
        app1.raiden,
        app0_restart.raiden.address,
        network_wait,
    )

    mediated_transfer(
        app2,
        app0_restart,
        token_network_identifier,
        amount,
        timeout=network_wait * number_of_nodes * 2,
    )
    mediated_transfer(
        app0_restart,
        app2,
        token_network_identifier,
        amount,
        timeout=network_wait * number_of_nodes * 2,
    )

    assert_synced_channel_state(
        token_network_identifier,
        app0_restart, deposit - spent_amount, [],
        app1, deposit + spent_amount, [],
    )
    assert_synced_channel_state(
        token_network_identifier,
        app1, deposit - spent_amount, [],
        app2, deposit + spent_amount, [],
    )
Exemplo n.º 37
0
def test_fullnetwork(raiden_chain, settle_timeout, reveal_timeout):
    app0, app1, app2, app3 = raiden_chain  # pylint: disable=unbalanced-tuple-unpacking
    token_address = app0.raiden.chain.default_registry.token_addresses()[0]
    channel_0_1 = channel(app0, app1, token_address)
    channel_1_2 = channel(app1, app2, token_address)
    channel_3_2 = channel(app3, app2, token_address)
    channel_0_3 = channel(app0, app3, token_address)

    amount = 80
    direct_transfer(app0, app1, token_address, amount)
    last_transfer = get_sent_transfer(channel_0_1, 0)
    assert last_transfer.transferred_amount == 80

    amount = 50
    direct_transfer(app1, app2, token_address, amount)
    last_transfer = get_sent_transfer(channel_1_2, 0)
    assert last_transfer.transferred_amount == 50

    amount = 30
    mediated_transfer(app0, app2, token_address, amount)
    last_transfer = get_sent_transfer(channel_0_1, 0)
    assert isinstance(last_transfer, DirectTransfer)

    initiator_transfer = get_sent_transfer(channel_0_3, 0)
    mediator_transfer = get_sent_transfer(channel_3_2, 0)
    assert initiator_transfer.identifier == mediator_transfer.identifier
    assert initiator_transfer.lock.amount == amount
    assert mediator_transfer.lock.amount == amount

    # Now let's query the WAL to see if the state changes were logged as expected
    app0_state_changes = [
        change[1]
        for change in get_all_state_changes(app0.raiden.transaction_log)
        if not isinstance(change[1], Block)
    ]
    app0_events = [
        event[2] for event in get_all_state_events(app0.raiden.transaction_log)
    ]
    app1_state_changes = [
        change[1]
        for change in get_all_state_changes(app1.raiden.transaction_log)
        if not isinstance(change[1], Block)
    ]
    app1_events = [
        event[2] for event in get_all_state_events(app1.raiden.transaction_log)
    ]
    app2_state_changes = [
        change[1]
        for change in get_all_state_changes(app2.raiden.transaction_log)
        if not isinstance(change[1], Block)
    ]
    app2_events = [
        event[2] for event in get_all_state_events(app2.raiden.transaction_log)
    ]
    app3_state_changes = [
        change[1]
        for change in get_all_state_changes(app3.raiden.transaction_log)
        if not isinstance(change[1], Block)
    ]
    app3_events = [
        event[2] for event in get_all_state_events(app3.raiden.transaction_log)
    ]

    # app1 does not take part in the mediated transfer.
    assert len(app1_state_changes) == 0
    assert len(app1_events) == 0

    # app0 initiates the mediated_transfer
    assert len(app0_state_changes) == 3
    assert isinstance(app0_state_changes[0], ActionInitInitiator)
    assert app0_state_changes[0].our_address == app0.raiden.address
    assert app0_state_changes[0].transfer.amount == amount
    assert app0_state_changes[0].transfer.token == token_address
    assert app0_state_changes[0].transfer.initiator == app0.raiden.address
    assert app0_state_changes[0].transfer.target == app2.raiden.address
    # The ActionInitInitiator state change does not have the following fields populated.
    # They get populated via an event during the processing of the state change inside
    # this function: mediated_transfer.mediated_transfer.initiator.try_new_route()
    assert app0_state_changes[0].transfer.expiration is None
    assert app0_state_changes[0].transfer.hashlock is None
    assert app0_state_changes[0].transfer.secret is None
    # We should have two available routes
    assert len(app0_state_changes[0].routes.available_routes) == 2
    assert len(app0_state_changes[0].routes.ignored_routes) == 0
    assert len(app0_state_changes[0].routes.refunded_routes) == 0
    assert len(app0_state_changes[0].routes.canceled_routes) == 0
    # Of these 2 the state machine will in the future choose the one with the most
    # available balance
    not_taken_route = RouteState(
        state='opened',
        node_address=app1.raiden.address,
        channel_address=channel_0_1.channel_address,
        available_balance=1048496,
        settle_timeout=settle_timeout,
        reveal_timeout=reveal_timeout,
        closed_block=None,
    )
    taken_route = RouteState(
        state='opened',
        node_address=app3.raiden.address,
        channel_address=channel_0_3.channel_address,
        available_balance=1048576,
        settle_timeout=settle_timeout,
        reveal_timeout=reveal_timeout,
        closed_block=None,
    )
    assert taken_route in app0_state_changes[0].routes.available_routes
    assert not_taken_route in app0_state_changes[0].routes.available_routes

    # app0 will also receive a secret request from the target
    assert isinstance(app0_state_changes[1], ReceiveSecretRequest)
    assert app0_state_changes[1].amount == amount
    assert app0_state_changes[1].sender == app2.raiden.address
    hashlock = app0_state_changes[1].hashlock

    # app0 will also receive a secret reveal from the immediate neighbour
    assert isinstance(app0_state_changes[2], ReceiveSecretReveal)
    assert app0_state_changes[2].sender == app3.raiden.address
    secret = app0_state_changes[2].secret
    assert sha3(secret) == hashlock

    # check app0 state events
    assert len(app0_events) == 4
    assert isinstance(app0_events[0], SendMediatedTransfer)
    assert app0_events[0].token == token_address
    assert app0_events[0].amount == amount
    assert app0_events[0].hashlock == hashlock
    assert app0_events[0].initiator == app0.raiden.address
    assert app0_events[0].target == app2.raiden.address
    assert app0_events[0].receiver == app3.raiden.address
    assert isinstance(app0_events[1], SendRevealSecret)
    assert app0_events[1].secret == secret
    assert app0_events[1].token == token_address
    assert app0_events[1].receiver == app2.raiden.address
    assert app0_events[1].sender == app0.raiden.address
    assert isinstance(app0_events[2], SendBalanceProof)
    assert app0_events[2].token == token_address
    assert app0_events[2].channel_address == channel_0_3.channel_address
    assert app0_events[2].receiver == app3.raiden.address
    assert app0_events[2].secret == secret
    assert isinstance(app0_events[3], EventTransferCompleted)
    assert app0_events[3].secret == secret
    assert app0_events[3].hashlock == hashlock

    # app3 is the mediator
    assert isinstance(app3_state_changes[0], ActionInitMediator)
    assert app3_state_changes[0].our_address == app3.raiden.address
    # We should have only 1 available route from mediator to target
    from_route = RouteState(
        state='opened',
        node_address=app0.raiden.address,
        channel_address=channel_0_3.channel_address,
        available_balance=1048576,
        settle_timeout=settle_timeout,
        reveal_timeout=reveal_timeout,
        closed_block=None,
    )
    to_route = RouteState(
        state='opened',
        node_address=app2.raiden.address,
        channel_address=channel_3_2.channel_address,
        available_balance=1048576,
        settle_timeout=settle_timeout,
        reveal_timeout=reveal_timeout,
        closed_block=None,
    )
    assert app3_state_changes[0].from_route == from_route
    assert len(app3_state_changes[0].routes.available_routes) == 1
    assert len(app3_state_changes[0].routes.ignored_routes) == 0
    assert len(app3_state_changes[0].routes.refunded_routes) == 0
    assert len(app3_state_changes[0].routes.canceled_routes) == 0
    assert app3_state_changes[0].routes.available_routes[0] == to_route
    # check the from_transfer is correct
    assert app3_state_changes[0].from_transfer.amount == amount
    assert app3_state_changes[0].from_transfer.hashlock == hashlock
    assert app3_state_changes[0].from_transfer.token == token_address
    assert app3_state_changes[0].from_transfer.initiator == app0.raiden.address
    assert app3_state_changes[0].from_transfer.target == app2.raiden.address

    # The mediator should have also received a SecretReveal from the target
    assert isinstance(app3_state_changes[1], ReceiveSecretReveal)
    assert app3_state_changes[1].sender == app2.raiden.address
    assert app3_state_changes[1].secret == secret

    # If the mediator received any more it is from the initiator
    # TODO: Figure out why we may get two times the secret reveal from the initiator
    for state_change in app3_state_changes[2:]:
        assert isinstance(state_change, ReceiveSecretReveal)
        assert state_change.sender == app0.raiden.address
        assert state_change.secret == secret

    # check app3 state events
    assert len(app3_events) == 3
    assert isinstance(app3_events[0], SendMediatedTransfer)
    assert app3_events[0].token == token_address
    assert app3_events[0].amount == amount
    assert app3_events[0].hashlock == hashlock
    assert app3_events[0].initiator == app0.raiden.address
    assert app3_events[0].target == app2.raiden.address
    assert app3_events[0].receiver == app2.raiden.address
    assert isinstance(app3_events[1], SendRevealSecret)
    assert app3_events[1].secret == secret
    assert app3_events[1].token == token_address
    assert app3_events[1].receiver == app0.raiden.address
    assert app3_events[1].sender == app3.raiden.address
    assert isinstance(app3_events[2], SendBalanceProof)
    assert app3_events[2].token == token_address
    assert app3_events[2].channel_address == channel_3_2.channel_address
    assert app3_events[2].receiver == app2.raiden.address
    assert app3_events[2].secret == secret

    # app2 is the target of the mediated transfer
    assert len(app2_state_changes
               ) == 4  # We get 2 secret reveals from the mediator. WHY?
    assert isinstance(app2_state_changes[0], ActionInitTarget)
    assert app2_state_changes[0].our_address == app2.raiden.address
    # check the route the transfer came from
    from_route = RouteState(
        state='opened',
        node_address=app3.raiden.address,
        channel_address=channel_3_2.channel_address,
        available_balance=1048576,
        settle_timeout=settle_timeout,
        reveal_timeout=reveal_timeout,
        closed_block=None,
    )
    assert app2_state_changes[0].from_route == from_route
    # check the from_transfer is correct
    assert app2_state_changes[0].from_transfer.amount == amount
    assert app2_state_changes[0].from_transfer.hashlock == hashlock
    assert app2_state_changes[0].from_transfer.token == token_address
    assert app2_state_changes[0].from_transfer.initiator == app0.raiden.address
    assert app2_state_changes[0].from_transfer.target == app2.raiden.address

    # We also get secret reveals from the initiator and the mediator.
    assert isinstance(app2_state_changes[1], ReceiveSecretReveal)
    assert app2_state_changes[1].sender == app0.raiden.address
    assert app2_state_changes[1].secret == secret

    # TODO: Figure out why we get two times the Secret Reveal from the mediator
    assert isinstance(app2_state_changes[2], ReceiveSecretReveal)
    assert app2_state_changes[2].sender == app3.raiden.address
    assert app2_state_changes[2].secret == secret
    assert isinstance(app2_state_changes[3], ReceiveSecretReveal)
    assert app2_state_changes[3].sender == app3.raiden.address
    assert app2_state_changes[3].secret == secret

    # check app2 state events
    assert len(app2_events) == 2
    assert isinstance(app2_events[0], SendSecretRequest)
    assert app2_events[0].amount == amount
    assert app2_events[0].hashlock == hashlock
    assert app2_events[0].receiver == app0.raiden.address
    assert isinstance(app2_events[1], SendRevealSecret)
    assert app2_events[1].token == token_address
    assert app2_events[1].secret == secret
    assert app2_events[1].receiver == app3.raiden.address
    assert app2_events[1].sender == app2.raiden.address
Exemplo n.º 38
0
def test_refund_transfer(
        raiden_chain,
        number_of_nodes,
        token_addresses,
        deposit,
        network_wait,
        retry_timeout,
        # UDP does not seem to retry messages until processed
        # https://github.com/raiden-network/raiden/issues/3185
        skip_if_not_matrix,
):
    """A failed transfer must send a refund back.

    TODO:
        - Unlock the token on refund #1091
        - Clear the merkletree and update the locked amount #193
        - Remove the refund message type #490"""
    # Topology:
    #
    #  0 -> 1 -> 2
    #
    app0, app1, app2 = raiden_chain
    token_address = token_addresses[0]
    payment_network_identifier = app0.raiden.default_registry.address
    token_network_identifier = views.get_token_network_identifier_by_token_address(
        views.state_from_app(app0),
        payment_network_identifier,
        token_address,
    )

    # make a transfer to test the path app0 -> app1 -> app2
    identifier_path = 1
    amount_path = 1
    mediated_transfer(
        app0,
        app2,
        token_network_identifier,
        amount_path,
        identifier_path,
        timeout=network_wait * number_of_nodes,
    )

    # drain the channel app1 -> app2
    identifier_drain = 2
    amount_drain = deposit * 8 // 10
    mediated_transfer(
        initiator_app=app1,
        target_app=app2,
        token_network_identifier=token_network_identifier,
        amount=amount_drain,
        identifier=identifier_drain,
        timeout=network_wait,
    )

    # wait for the nodes to sync
    gevent.sleep(0.2)

    assert_synced_channel_state(
        token_network_identifier,
        app0, deposit - amount_path, [],
        app1, deposit + amount_path, [],
    )
    assert_synced_channel_state(
        token_network_identifier,
        app1, deposit - amount_path - amount_drain, [],
        app2, deposit + amount_path + amount_drain, [],
    )

    # app0 -> app1 -> app2 is the only available path, but the channel app1 ->
    # app2 doesn't have capacity, so a refund will be sent on app1 -> app0
    identifier_refund = 3
    amount_refund = 50
    async_result = app0.raiden.mediated_transfer_async(
        token_network_identifier,
        amount_refund,
        app2.raiden.address,
        identifier_refund,
    )
    assert async_result.wait() is False, 'there is no path with capacity, the transfer must fail'

    gevent.sleep(0.2)

    # A lock structure with the correct amount

    send_locked = raiden_events_must_contain_entry(
        app0.raiden,
        SendLockedTransfer,
        {'transfer': {'lock': {'amount': amount_refund}}},
    )
    assert send_locked
    secrethash = send_locked.transfer.lock.secrethash

    send_refund = raiden_events_must_contain_entry(app1.raiden, SendRefundTransfer, {})
    assert send_refund

    lock = send_locked.transfer.lock
    refund_lock = send_refund.transfer.lock
    assert lock.amount == refund_lock.amount
    assert lock.secrethash
    assert lock.expiration
    assert lock.secrethash == refund_lock.secrethash

    # Both channels have the amount locked because of the refund message
    assert_synced_channel_state(
        token_network_identifier,
        app0, deposit - amount_path, [lockstate_from_lock(lock)],
        app1, deposit + amount_path, [lockstate_from_lock(refund_lock)],
    )
    assert_synced_channel_state(
        token_network_identifier,
        app1, deposit - amount_path - amount_drain, [],
        app2, deposit + amount_path + amount_drain, [],
    )

    # Additional checks for LockExpired causing nonce mismatch after refund transfer:
    # https://github.com/raiden-network/raiden/issues/3146#issuecomment-447378046
    # At this point make sure that the initiator has not deleted the payment task
    assert secrethash in state_from_raiden(app0.raiden).payment_mapping.secrethashes_to_task

    # Wait for lock lock expiration but make sure app0 never processes LockExpired
    with dont_handle_lock_expired_mock(app0):
        wait_for_block(
            raiden=app0.raiden,
            block_number=channel.get_sender_expiration_threshold(lock) + 1,
            retry_timeout=retry_timeout,
        )
        # make sure that app0 still has the payment task for the secrethash
        # https://github.com/raiden-network/raiden/issues/3183
        assert secrethash in state_from_raiden(app0.raiden).payment_mapping.secrethashes_to_task

        # make sure that app1 sent a lock expired message for the secrethash
        send_lock_expired = raiden_events_must_contain_entry(
            app1.raiden,
            SendLockExpired,
            {'secrethash': secrethash},
        )
        assert send_lock_expired
        # make sure that app0 never got it
        state_changes = app0.raiden.wal.storage.get_statechanges_by_identifier(0, 'latest')
        assert not must_contain_entry(
            state_changes,
            ReceiveLockExpired,
            {'secrethash': secrethash},
        )

    # Out of the handicapped app0 transport.
    # Now wait till app0 receives and processes LockExpired
    receive_lock_expired = wait_for_state_change(
        app0.raiden,
        ReceiveLockExpired,
        {'secrethash': secrethash},
        retry_timeout,
    )
    # And also till app1 received the processed
    wait_for_state_change(
        app1.raiden,
        ReceiveProcessed,
        {'message_identifier': receive_lock_expired.message_identifier},
        retry_timeout,
    )

    # make sure app1 queue has cleared the SendLockExpired
    chain_state1 = views.state_from_app(app1)
    queues1 = views.get_all_messagequeues(chain_state=chain_state1)
    result = [
        (queue_id, queue)
        for queue_id, queue in queues1.items()
        if queue_id.recipient == app0.raiden.address and
        queue
    ]
    assert not result

    # and now wait for 1 more block so that the payment task can be deleted
    wait_for_block(
        raiden=app0.raiden,
        block_number=app0.raiden.get_block_number() + 1,
        retry_timeout=retry_timeout,
    )

    # and since the lock expired message has been sent and processed then the
    # payment task should have been deleted from both nodes
    # https://github.com/raiden-network/raiden/issues/3183
    assert secrethash not in state_from_raiden(app0.raiden).payment_mapping.secrethashes_to_task
    assert secrethash not in state_from_raiden(app1.raiden).payment_mapping.secrethashes_to_task
Exemplo n.º 39
0
def test_different_view_of_last_bp_during_unlock(
    raiden_chain,
    number_of_nodes,
    token_addresses,
    deposit,
    network_wait,
    retry_timeout,
    # UDP does not seem to retry messages until processed
    # https://github.com/raiden-network/raiden/issues/3185
    skip_if_not_matrix,
):
    """Test for https://github.com/raiden-network/raiden/issues/3196#issuecomment-449163888"""
    # Topology:
    #
    #  0 -> 1 -> 2
    #
    app0, app1, app2 = raiden_chain
    token_address = token_addresses[0]
    payment_network_identifier = app0.raiden.default_registry.address
    token_network_identifier = views.get_token_network_identifier_by_token_address(
        views.state_from_app(app0),
        payment_network_identifier,
        token_address,
    )
    token_proxy = app0.raiden.chain.token(token_address)
    initial_balance0 = token_proxy.balance_of(app0.raiden.address)
    initial_balance1 = token_proxy.balance_of(app1.raiden.address)

    # make a transfer to test the path app0 -> app1 -> app2
    identifier_path = 1
    amount_path = 1
    mediated_transfer(
        app0,
        app2,
        token_network_identifier,
        amount_path,
        identifier_path,
        timeout=network_wait * number_of_nodes,
    )

    # drain the channel app1 -> app2
    identifier_drain = 2
    amount_drain = deposit * 8 // 10
    mediated_transfer(
        initiator_app=app1,
        target_app=app2,
        token_network_identifier=token_network_identifier,
        amount=amount_drain,
        identifier=identifier_drain,
        timeout=network_wait,
    )

    # wait for the nodes to sync
    gevent.sleep(0.2)

    assert_synced_channel_state(
        token_network_identifier,
        app0,
        deposit - amount_path,
        [],
        app1,
        deposit + amount_path,
        [],
    )
    assert_synced_channel_state(
        token_network_identifier,
        app1,
        deposit - amount_path - amount_drain,
        [],
        app2,
        deposit + amount_path + amount_drain,
        [],
    )

    # app0 -> app1 -> app2 is the only available path, but the channel app1 ->
    # app2 doesn't have capacity, so a refund will be sent on app1 -> app0
    identifier_refund = 3
    amount_refund = 50
    payment_status = app0.raiden.mediated_transfer_async(
        token_network_identifier,
        amount_refund,
        app2.raiden.address,
        identifier_refund,
    )
    msg = 'there is no path with capacity, the transfer must fail'
    assert payment_status.payment_done.wait() is False, msg

    gevent.sleep(0.2)

    # A lock structure with the correct amount

    send_locked = raiden_events_search_for_item(
        app0.raiden,
        SendLockedTransfer,
        {'transfer': {
            'lock': {
                'amount': amount_refund
            }
        }},
    )
    assert send_locked
    secrethash = send_locked.transfer.lock.secrethash

    send_refund = raiden_events_search_for_item(app1.raiden,
                                                SendRefundTransfer, {})
    assert send_refund

    lock = send_locked.transfer.lock
    refund_lock = send_refund.transfer.lock
    assert lock.amount == refund_lock.amount
    assert lock.secrethash
    assert lock.expiration
    assert lock.secrethash == refund_lock.secrethash

    # Both channels have the amount locked because of the refund message
    assert_synced_channel_state(
        token_network_identifier,
        app0,
        deposit - amount_path,
        [lock],
        app1,
        deposit + amount_path,
        [refund_lock],
    )
    assert_synced_channel_state(
        token_network_identifier,
        app1,
        deposit - amount_path - amount_drain,
        [],
        app2,
        deposit + amount_path + amount_drain,
        [],
    )

    # Additional checks for LockExpired causing nonce mismatch after refund transfer:
    # https://github.com/raiden-network/raiden/issues/3146#issuecomment-447378046
    # At this point make sure that the initiator has not deleted the payment task
    assert secrethash in state_from_raiden(
        app0.raiden).payment_mapping.secrethashes_to_task

    with dont_handle_node_change_network_state():
        # now app1 goes offline
        app1.raiden.stop()
        app1.raiden.get()
        assert not app1.raiden

        # Wait for lock expiration so that app0 sends a LockExpired
        wait_for_block(
            raiden=app0.raiden,
            block_number=channel.get_sender_expiration_threshold(lock) + 1,
            retry_timeout=retry_timeout,
        )

        # make sure that app0 sent a lock expired message for the secrethash
        wait_for_raiden_event(
            app0.raiden,
            SendLockExpired,
            {'secrethash': secrethash},
            retry_timeout,
        )

        # now app0 closes the channel
        RaidenAPI(app0.raiden).channel_close(
            registry_address=payment_network_identifier,
            token_address=token_address,
            partner_address=app1.raiden.address,
        )

    count = 0
    original_update = app1.raiden.raiden_event_handler.handle_contract_send_channelupdate

    def patched_update(raiden, event):
        nonlocal count
        count += 1
        original_update(raiden, event)

    app1.raiden.raiden_event_handler.handle_contract_send_channelupdate = patched_update
    # and now app1 comes back online
    app1.raiden.start()
    # test for https://github.com/raiden-network/raiden/issues/3216
    assert count == 1, 'Update transfer should have only been called once during restart'
    channel_identifier = get_channelstate(app0, app1,
                                          token_network_identifier).identifier

    # and we wait for settlement
    wait_for_settle(
        raiden=app0.raiden,
        payment_network_id=payment_network_identifier,
        token_address=token_address,
        channel_ids=[channel_identifier],
        retry_timeout=app0.raiden.alarm.sleep_time,
    )

    with gevent.Timeout(10):
        unlock_app0 = wait_for_state_change(
            app0.raiden,
            ContractReceiveChannelBatchUnlock,
            {'participant': app0.raiden.address},
            retry_timeout,
        )
    assert unlock_app0.returned_tokens == 50
    with gevent.Timeout(10):
        unlock_app1 = wait_for_state_change(
            app1.raiden,
            ContractReceiveChannelBatchUnlock,
            {'participant': app1.raiden.address},
            retry_timeout,
        )
    assert unlock_app1.returned_tokens == 50
    final_balance0 = token_proxy.balance_of(app0.raiden.address)
    final_balance1 = token_proxy.balance_of(app1.raiden.address)

    assert final_balance0 - deposit - initial_balance0 == -1
    assert final_balance1 - deposit - initial_balance1 == 1
Exemplo n.º 40
0
def test_recovery_happy_case(
        raiden_network,
        number_of_nodes,
        deposit,
        token_addresses,
        network_wait,
        skip_if_not_udp,
):
    app0, app1, app2 = raiden_network
    token_address = token_addresses[0]

    app2_wait_for = WaitForMessage()
    app2.raiden.message_handler = app2_wait_for

    chain_state = views.state_from_app(app0)
    payment_network_id = app0.raiden.default_registry.address
    token_network_identifier = views.get_token_network_identifier_by_token_address(
        chain_state,
        payment_network_id,
        token_address,
    )

    # make a few transfers from app0 to app2
    amount = 1
    spent_amount = deposit - 2
    for _ in range(spent_amount):
        mediated_transfer(
            app0,
            app2,
            token_network_identifier,
            amount,
            timeout=network_wait * number_of_nodes,
        )

    app0.raiden.stop()
    host_port = (
        app0.raiden.config['transport']['udp']['host'],
        app0.raiden.config['transport']['udp']['port'],
    )
    socket = server._udp_socket(host_port)

    new_transport = UDPTransport(
        app0.raiden.address,
        app0.discovery,
        socket,
        app0.raiden.transport.throttle_policy,
        app0.raiden.config['transport']['udp'],
    )

    raiden_event_handler = RaidenEventHandler()
    message_handler = MessageHandler()

    app0_restart = App(
        config=app0.config,
        chain=app0.raiden.chain,
        query_start_block=0,
        default_registry=app0.raiden.default_registry,
        default_secret_registry=app0.raiden.default_secret_registry,
        transport=new_transport,
        raiden_event_handler=raiden_event_handler,
        message_handler=message_handler,
        discovery=app0.raiden.discovery,
    )

    app0.stop()
    del app0  # from here on the app0_restart should be used

    app0_restart.start()

    assert_synced_channel_state(
        token_network_identifier,
        app0_restart, deposit - spent_amount, [],
        app1, deposit + spent_amount, [],
    )
    assert_synced_channel_state(
        token_network_identifier,
        app1, deposit - spent_amount, [],
        app2, deposit + spent_amount, [],
    )

    # wait for the nodes' healthcheck to update the network statuses
    waiting.wait_for_healthy(
        app0_restart.raiden,
        app1.raiden.address,
        network_wait,
    )
    waiting.wait_for_healthy(
        app1.raiden,
        app0_restart.raiden.address,
        network_wait,
    )

    identifier = create_default_identifier()
    wait_for_payment = app2_wait_for.wait_for_message(Secret, {'payment_identifier': identifier})

    mediated_transfer(
        app2,
        app0_restart,
        token_network_identifier,
        amount,
        timeout=network_wait * number_of_nodes * 2,
    )
    mediated_transfer(
        initiator_app=app0_restart,
        target_app=app2,
        token_network_identifier=token_network_identifier,
        amount=amount,
        identifier=identifier,
        timeout=network_wait * number_of_nodes * 2,
    )

    assert_synced_channel_state(
        token_network_identifier,
        app0_restart, deposit - spent_amount, [],
        app1, deposit + spent_amount, [],
    )

    wait_for_payment.wait()
    assert_synced_channel_state(
        token_network_identifier,
        app1, deposit - spent_amount, [],
        app2, deposit + spent_amount, [],
    )
Exemplo n.º 41
0
def test_invalid_close(
        raiden_network,
        number_of_nodes,
        deposit,
        token_addresses,
        network_wait,
):
    app0, app1 = raiden_network
    token_address = token_addresses[0]
    chain_state = views.state_from_app(app0)
    payment_network_id = app0.raiden.default_registry.address
    registry_address = app0.raiden.default_registry.address
    token_network_identifier = views.get_token_network_identifier_by_token_address(
        chain_state=chain_state,
        payment_network_id=payment_network_id,
        token_address=token_address,
    )
    channel_identifier = get_channelstate(app0, app1, token_network_identifier).identifier

    # make a transfer from app0 to app1 so that app1 is supposed to have a non empty balance hash
    mediated_transfer(
        initiator_app=app0,
        target_app=app1,
        token_network_identifier=token_network_identifier,
        amount=1,
        timeout=network_wait * number_of_nodes,
    )
    # stop app1 - the test uses token_network_contract now
    app1.stop()
    token_network_contract = TokenNetwork(
        jsonrpc_client=app1.raiden.chain.client,
        manager_address=token_network_identifier,
        contract_manager=app1.raiden.contract_manager,
    )

    # app1 closes the channel with an empty hash instead of the expected hash
    # of the transferred amount from app0
    token_network_contract.close(
        channel_identifier=channel_identifier,
        partner=app0.raiden.address,
        balance_hash=EMPTY_HASH,
        nonce=0,
        additional_hash=EMPTY_HASH,
        signature=EMPTY_SIGNATURE,
    )
    waiting.wait_for_close(
        raiden=app0.raiden,
        payment_network_id=registry_address,
        token_address=token_address,
        channel_ids=[channel_identifier],
        retry_timeout=app0.raiden.alarm.sleep_time,
    )
    waiting.wait_for_settle(
        raiden=app0.raiden,
        payment_network_id=registry_address,
        token_address=token_address,
        channel_ids=[channel_identifier],
        retry_timeout=app0.raiden.alarm.sleep_time,
    )
    state_changes = app0.raiden.wal.storage.get_statechanges_by_identifier(
        from_identifier=0,
        to_identifier='latest',
    )
    assert must_contain_entry(state_changes, ContractReceiveChannelSettled, {
        'token_network_identifier': token_network_identifier,
        'channel_identifier': channel_identifier,
    })