Beispiel #1
0
def run_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
    transfer(
        initiator_app=app0,
        target_app=app2,
        token_address=token_address,
        amount=amount,
        identifier=1,
        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,
        payment_hash_invoice=EMPTY_PAYMENT_HASH_INVOICE,
        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=amount,
                  expiration=expiration,
                  secrethash=UNIT_SECRETHASH),
        target=app2.raiden.address,
        initiator=app0.raiden.address,
        fee=0,
    )

    sign_and_inject(mediated_transfer_message, app0.raiden.signer, app1)

    with gevent.Timeout(network_wait):
        wait_assert(
            assert_synced_channel_state,
            token_network_identifier,
            app0,
            deposit - amount,
            [],
            app1,
            deposit + amount,
            [],
        )
Beispiel #2
0
def run_test_create_monitoring_request(raiden_network, token_addresses):
    app0, app1 = 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=chain_state,
        payment_network_id=payment_network_id,
        token_address=token_address,
    )

    payment_identifier = create_default_identifier()
    transfer(
        initiator_app=app1,
        target_app=app0,
        token_address=token_address,
        amount=1,
        identifier=payment_identifier,
    )
    chain_state = views.state_from_raiden(app0.raiden)
    channel_state = views.get_channelstate_by_token_network_and_partner(
        chain_state,
        token_network_identifier,
        app1.raiden.address,
    )
    balance_proof = channel_state.partner_state.balance_proof
    api = RaidenAPI(app0.raiden)
    request = api.create_monitoring_request(
        balance_proof=balance_proof,
        reward_amount=1,
    )
    assert request
    as_dict = request.to_dict()
    from_dict = RequestMonitoring.from_dict(as_dict)
    assert from_dict.to_dict() == as_dict
def run_regression_payment_complete_after_refund_to_the_initiator(
        raiden_network, token_addresses, settle_timeout, deposit):
    app0, app1, app2, app3, app4 = raiden_network
    token = token_addresses[0]
    registry_address = app0.raiden.default_registry.address

    # Topology:
    #
    #  0 -> 1 -> 2
    #  v         ^
    #  3 ------> 4
    app_channels = [(app0, app1), (app1, app2), (app0, app3), (app3, app4),
                    (app4, app2)]

    open_and_wait_for_channels(app_channels, registry_address, token, deposit,
                               settle_timeout)

    # Use all deposit from app1->app2 to force a refund
    transfer(initiator_app=app1,
             target_app=app2,
             token_address=token,
             amount=deposit,
             identifier=1)

    # Send a refund that will refund the initiator
    transfer(initiator_app=app0,
             target_app=app2,
             token_address=token,
             amount=deposit,
             identifier=1)

    assert raiden_state_changes_search_for_item(
        raiden=app0, item_type=ReceiveTransferRefundCancelRoute, attributes={})
Beispiel #4
0
def test_api_channel_events(raiden_chain, token_addresses):
    app0, app1 = raiden_chain
    token_address = token_addresses[0]

    amount = PaymentAmount(30)
    transfer(
        initiator_app=app0,
        target_app=app1,
        token_address=token_address,
        amount=amount,
        identifier=PaymentID(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()
    assert any(
        isinstance(event, EventPaymentSentSuccess) for event in app0_events)

    app1_events = app1.raiden.wal.storage.get_events()
    assert 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})
Beispiel #5
0
def test_regression_unfiltered_routes(raiden_network, token_addresses,
                                      settle_timeout, deposit):
    """ The transfer should proceed without triggering an assert.

    Transfers failed in networks where two or more paths to the destination are
    possible but they share same node as a first hop.
    """
    app0, app1, app2, app3, app4 = raiden_network
    token = token_addresses[0]
    registry_address = app0.raiden.default_registry.address

    # Topology:
    #
    #  0 -> 1 -> 2 -> 4
    #       |         ^
    #       +--> 3 ---+
    app_channels = [(app0, app1), (app1, app2), (app1, app3), (app3, app4),
                    (app2, app4)]

    open_and_wait_for_channels(app_channels, registry_address, token, deposit,
                               settle_timeout)
    transfer(
        initiator_app=app0,
        target_app=app4,
        token_address=token,
        amount=PaymentAmount(1),
        identifier=PaymentID(1),
    )
Beispiel #6
0
def test_create_monitoring_request(raiden_network, token_addresses):
    app0, app1 = raiden_network
    token_address = token_addresses[0]
    chain_state = views.state_from_app(app0)
    token_network_registry_address = app0.raiden.default_registry.address
    token_network_address = views.get_token_network_address_by_token_address(
        chain_state=chain_state,
        token_network_registry_address=token_network_registry_address,
        token_address=token_address,
    )
    assert token_network_address

    payment_identifier = create_default_identifier()
    transfer(
        initiator_app=app1,
        target_app=app0,
        token_address=token_address,
        amount=PaymentAmount(1),
        identifier=payment_identifier,
    )
    chain_state = views.state_from_raiden(app0.raiden)
    channel_state = views.get_channelstate_by_token_network_and_partner(
        chain_state, token_network_address, app1.raiden.address)
    assert channel_state
    balance_proof = cast(BalanceProofSignedState,
                         channel_state.partner_state.balance_proof)
    api = RaidenAPI(app0.raiden)
    request = api.create_monitoring_request(balance_proof=balance_proof,
                                            reward_amount=TokenAmount(1))
    assert request
    as_dict = DictSerializer.serialize(request)
    from_dict = DictSerializer.deserialize(as_dict)
    assert DictSerializer.serialize(from_dict) == as_dict
Beispiel #7
0
def run_test_regression_transport_global_queues_are_initialized_on_restart_for_services(
        raiden_network, number_of_nodes, token_addresses, network_wait,
        user_deposit_address):
    app0, app1 = raiden_network

    app0.config["services"]["monitoring_enabled"] = True

    # Send a transfer to make sure the state has a balance proof
    # to publish to the global matrix rooms
    token_address = token_addresses[0]

    amount = 10
    transfer(
        initiator_app=app1,
        target_app=app0,
        token_address=token_address,
        amount=amount,
        identifier=1,
        timeout=network_wait * number_of_nodes,
    )

    app0.stop()

    transport = MatrixTransport(app0.config["transport"]["matrix"])
    transport.send_async = Mock()
    transport._send_raw = Mock()

    old_start_transport = transport.start

    # Check that the queue is populated before the transport sends it and empties the queue
    def start_transport(*args, **kwargs):
        # Before restart the transport's global message queue should be initialized
        # There should be 2 messages in the global queue.
        # 1 for the PFS and the other for MS
        assert len(transport._global_send_queue) == 2
        # No other messages were sent at this point
        transport.send_async.assert_not_called()
        transport._send_raw.assert_not_called()
        old_start_transport(*args, **kwargs)

    transport.start = start_transport

    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_one_to_n_address=app0.raiden.default_one_to_n_address,
        default_secret_registry=app0.raiden.default_secret_registry,
        default_service_registry=app0.raiden.default_service_registry,
        transport=transport,
        raiden_event_handler=raiden_event_handler,
        message_handler=message_handler,
        discovery=app0.raiden.discovery,
        user_deposit=app0.raiden.chain.user_deposit(user_deposit_address),
    )
    app0_restart.start()
Beispiel #8
0
def run_test_mediated_transfer_with_entire_deposit(
    raiden_network,
    number_of_nodes,
    token_addresses,
    deposit,
    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,
    )
    transfer(
        initiator_app=app0,
        target_app=app2,
        token_address=token_address,
        amount=deposit,
        identifier=1,
        timeout=network_wait * number_of_nodes,
    )

    transfer(
        initiator_app=app2,
        target_app=app0,
        token_address=token_address,
        amount=deposit * 2,
        identifier=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,
            [],
        )
def run_test_node_can_settle_if_partner_does_not_call_update_transfer(
    raiden_network,
    number_of_nodes,
    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

    transfer(
        initiator_app=app0,
        target_app=app1,
        token_address=token_address,
        amount=1,
        identifier=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,
    )

    # 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,
        },
    )
Beispiel #10
0
def test_cancel_transfer(raiden_chain, token, deposit):

    app0, app1, app2, app3 = raiden_chain  # pylint: disable=unbalanced-tuple-unpacking

    messages = setup_messages_cb()
    mlogger = MessageLogger()

    assert_synched_channels(channel(app0, app1, token), deposit, [],
                            channel(app1, app0, token), deposit, [])

    assert_synched_channels(channel(app1, app2, token), deposit, [],
                            channel(app2, app1, token), deposit, [])

    assert_synched_channels(channel(app2, app3, token), deposit, [],
                            channel(app3, app2, token), deposit, [])

    assert_synched_channels(channel(app0, app1, token), deposit, [],
                            channel(app1, app0, token), deposit, [])

    # drain the channel app1 -> app2
    amount12 = 50
    direct_transfer(app1, app2, token, amount12, identifier=1)

    # drain the channel app2 -> app3
    amount23 = 80
    direct_transfer(app2, app3, token, amount23, identifier=2)

    assert_synched_channels(channel(app1, app2, token), deposit - amount12, [],
                            channel(app2, app1, token), deposit + amount12, [])

    assert_synched_channels(channel(app2, app3, token), deposit - amount23, [],
                            channel(app3, app2, token), deposit + amount23, [])

    # app1 -> app3 is the only available path but app2 -> app3 doesnt have
    # resources and needs to send a RefundTransfer down the path
    transfer(app0, app3, token, amount=50, identifier=1)

    assert_synched_channels(channel(app0, app1, token), deposit, [],
                            channel(app1, app0, token), deposit, [])

    assert_synched_channels(channel(app1, app2, token), deposit - amount12, [],
                            channel(app2, app1, token), deposit + amount12, [])

    assert_synched_channels(channel(app2, app3, token), deposit - amount23, [],
                            channel(app3, app2, token), deposit + amount23, [])

    assert len(unique(messages)) == 12  # DT + DT + SMT + MT + RT + RT + ACKs

    app1_messages = mlogger.get_node_messages(pex(app1.raiden.address),
                                              only='sent')
    assert isinstance(app1_messages[-1], RefundTransfer)

    app2_messages = mlogger.get_node_messages(pex(app2.raiden.address),
                                              only='sent')
    assert isinstance(app2_messages[-1], RefundTransfer)
Beispiel #11
0
def test_cancel_transfer():
    deposit = 100
    asset = sha3('test_cancel_transfer')[:20]

    # pylint: disable=unbalanced-tuple-unpacking
    app0, app1, app2 = create_sequential_network(num_nodes=3, deposit=deposit, asset=asset)

    messages = setup_messages_cb()
    mlogger = MessageLogger()

    assert_synched_channels(
        channel(app0, app1, asset), deposit, [],
        channel(app1, app0, asset), deposit, []
    )

    assert_synched_channels(
        channel(app1, app2, asset), deposit, [],
        channel(app2, app1, asset), deposit, []
    )

    # drain the channel app1 -> app2
    amount = 80
    direct_transfer(app1, app2, asset, amount)

    assert_synched_channels(
        channel(app0, app1, asset), deposit, [],
        channel(app1, app0, asset), deposit, []
    )

    assert_synched_channels(
        channel(app1, app2, asset), deposit - amount, [],
        channel(app2, app1, asset), deposit + amount, []
    )

    # app1 -> app2 is the only available path and doens't have resource, app1
    # needs to send CancelTransfer to app0
    transfer(app0, app2, asset, 50)

    assert_synched_channels(
        channel(app0, app1, asset), deposit, [],
        channel(app1, app0, asset), deposit, []
    )

    assert_synched_channels(
        channel(app1, app2, asset), deposit - amount, [],
        channel(app2, app1, asset), deposit + amount, []
    )

    assert len(messages) == 6  # DirectTransfer + MediatedTransfer + CancelTransfer + a Ack for each

    app1_messages = mlogger.get_node_messages(pex(app1.raiden.address), only='sent')

    assert isinstance(app1_messages[-1], CancelTransfer)
Beispiel #12
0
def test_handle_insufficient_eth(raiden_network, token_addresses, caplog):
    app0, app1 = raiden_network
    token = token_addresses[0]
    registry_address = app0.raiden.default_registry.address

    channel_state = views.get_channelstate_for(
        chain_state=views.state_from_raiden(app0.raiden),
        token_network_registry_address=registry_address,
        token_address=token,
        partner_address=app1.raiden.address,
    )
    assert isinstance(channel_state, NettingChannelState)
    channel_identifier = channel_state.identifier

    transfer(
        initiator_app=app0,
        target_app=app1,
        amount=PaymentAmount(1),
        token_address=token,
        identifier=PaymentID(1),
        timeout=60,
    )

    app1.raiden.stop()
    burn_eth(app1.raiden.rpc_client)
    app1.raiden.start()

    settle_block_timeout = BlockTimeout(
        exception_to_throw=RuntimeError("Settle did not happen."),
        raiden=app0.raiden,
        block_number=app0.raiden.get_block_number() + channel_state.settle_timeout * 2,
        retry_timeout=DEFAULT_RETRY_TIMEOUT,
    )

    with settle_block_timeout:
        RaidenAPI(app0.raiden).channel_close(
            registry_address=registry_address,
            token_address=token,
            partner_address=app1.raiden.address,
        )

        waiting.wait_for_settle(
            raiden=app0.raiden,
            token_network_registry_address=registry_address,
            token_address=token,
            channel_ids=[channel_identifier],
            retry_timeout=DEFAULT_RETRY_TIMEOUT,
        )

    assert any(
        "subtask died" in message and "insufficient ETH" in message for message in caplog.messages
    )
Beispiel #13
0
def test_regression_payment_complete_after_refund_to_the_initiator(
        raiden_network: List[RaidenService], token_addresses, settle_timeout,
        deposit):
    """Regression test for issue #3915"""
    app0, app1, app2, app3, app4 = raiden_network
    token = token_addresses[0]
    registry_address = app0.default_registry.address

    # Topology:
    #
    #  0 -> 1 -> 2
    #  |         ^
    #  v         |
    #  3 ------> 4

    app_channels = [(app0, app1), (app1, app2), (app0, app3), (app3, app4),
                    (app4, app2)]
    open_and_wait_for_channels(app_channels, registry_address, token, deposit,
                               settle_timeout)

    # Use all deposit from app1->app2 to force a refund
    transfer(
        initiator_app=app1,
        target_app=app2,
        token_address=token,
        amount=deposit,
        identifier=PaymentID(1),
        routes=[[app1.address, app2.address]],
    )

    # Send a transfer that will result in a refund app1->app0
    transfer(
        initiator_app=app0,
        target_app=app2,
        token_address=token,
        amount=PaymentAmount(50),
        identifier=PaymentID(2),
        timeout=20,
        expect_unlock_failures=True,
        routes=[
            [app0.address, app1.address, app2.address],
            [app0.address, app3.address, app4.address, app2.address],
        ],
    )

    assert raiden_state_changes_search_for_item(
        raiden=app0, item_type=ReceiveTransferCancelRoute, attributes={})
    assert raiden_events_search_for_item(raiden=app0,
                                         item_type=EventRouteFailed,
                                         attributes={})
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_address = views.get_token_network_address_by_token_address(
        views.state_from_app(app0), app0.raiden.default_registry.address,
        token_address)
    assert token_network_address
    channel0 = get_channelstate(app0, app1, token_network_address)

    amount = 10
    payment_identifier = PaymentID(1)
    secrethash = transfer(
        initiator_app=app0,
        target_app=app2,
        token_address=token_address,
        amount=PaymentAmount(10),
        identifier=payment_identifier,
        timeout=network_wait * number_of_nodes,
    )

    repeated_nonce = Nonce(1)
    expiration = reveal_timeout * 2
    mediated_transfer_message = LockedTransfer(
        chain_id=UNIT_CHAIN_ID,
        message_identifier=make_message_identifier(),
        payment_identifier=payment_identifier,
        nonce=repeated_nonce,
        token_network_address=token_network_address,
        token=token_address,
        channel_identifier=channel0.identifier,
        transferred_amount=TokenAmount(amount),
        locked_amount=TokenAmount(amount),
        recipient=app1.raiden.address,
        locksroot=make_locksroot(),
        lock=Lock(amount=PaymentWithFeeAmount(amount),
                  expiration=expiration,
                  secrethash=UNIT_SECRETHASH),
        target=app2.raiden.address,
        initiator=app0.raiden.address,
        signature=EMPTY_SIGNATURE,
        metadata=Metadata(routes=[
            RouteMetadata(route=[app1.raiden.address, app2.raiden.address])
        ]),
    )

    sign_and_inject(mediated_transfer_message, app0.raiden.signer, app1)

    with block_timeout_for_transfer_by_secrethash(app1.raiden, secrethash):
        wait_assert(
            assert_synced_channel_state,
            token_network_address,
            app0,
            deposit - amount,
            [],
            app1,
            deposit + amount,
            [],
        )
Beispiel #15
0
def test_handle_insufficient_eth(
    raiden_network: List[RaidenService], restart_node, token_addresses, caplog
):
    app0, app1 = raiden_network
    token = token_addresses[0]
    registry_address = app0.default_registry.address

    channel_state = views.get_channelstate_for(
        chain_state=views.state_from_raiden(app0),
        token_network_registry_address=registry_address,
        token_address=token,
        partner_address=app1.address,
    )
    assert isinstance(channel_state, NettingChannelState)
    channel_identifier = channel_state.identifier

    with block_offset_timeout(app0):
        transfer(
            initiator_app=app0,
            target_app=app1,
            token_address=token,
            amount=PaymentAmount(1),
            identifier=PaymentID(1),
        )

    app1.stop()
    burn_eth(app1.rpc_client)
    restart_node(app1)

    block_offset = BlockOffset(channel_state.settle_timeout * 2)
    with block_offset_timeout(app0, "Settle did not happen", block_offset):
        RaidenAPI(app0).channel_close(
            registry_address=registry_address,
            token_address=token,
            partner_address=app1.address,
        )
        waiting.wait_for_settle(
            raiden=app0,
            token_network_registry_address=registry_address,
            token_address=token,
            channel_ids=[channel_identifier],
            retry_timeout=DEFAULT_RETRY_TIMEOUT,
        )

    assert any(
        "subtask died" in message and "insufficient ETH" in message for message in caplog.messages
    )
def run_test_mediated_transfer_events(
        raiden_network,
        number_of_nodes,
        token_addresses,
        network_wait,
):
    app0, app1, app2 = raiden_network
    token_address = token_addresses[0]

    amount = 10
    transfer(
        initiator_app=app0,
        target_app=app2,
        token_address=token_address,
        amount=amount,
        identifier=1,
        timeout=network_wait * number_of_nodes,
    )

    def test_initiator_events():
        initiator_events = app0.raiden.wal.storage.get_events()
        return (
            search_for_item(initiator_events, SendSecretReveal, {}) and
            search_for_item(initiator_events, EventUnlockSuccess, {})
        )

    assert wait_until(test_initiator_events, network_wait)

    def test_mediator_events():
        mediator_events = app1.raiden.wal.storage.get_events()
        return (
            search_for_item(mediator_events, EventUnlockSuccess, {}) and
            search_for_item(mediator_events, EventUnlockClaimSuccess, {})
        )

    assert wait_until(test_mediator_events, network_wait)

    def test_target_events():
        target_events = app2.raiden.wal.storage.get_events()
        return (
            search_for_item(target_events, SendSecretRequest, {}) and
            search_for_item(target_events, SendSecretReveal, {}) and
            search_for_item(target_events, EventUnlockClaimSuccess, {})
        )

    assert wait_until(test_target_events, network_wait)
def test_mediated_transfer_events(raiden_network, number_of_nodes,
                                  token_addresses, network_wait):
    app0, app1, app2 = raiden_network
    token_address = token_addresses[0]

    amount = 10
    transfer(
        initiator_app=app0,
        target_app=app2,
        token_address=token_address,
        amount=PaymentAmount(amount),
        identifier=PaymentID(1),
        timeout=network_wait * number_of_nodes,
        routes=[[app0.address, app1.address, app2.address]],
    )

    def test_initiator_events():
        assert not has_unlock_failure(app0)
        initiator_events = app0.wal.storage.get_events()
        secret_reveal = search_for_item(initiator_events, SendSecretReveal, {})
        unlock_success = search_for_item(initiator_events, EventUnlockSuccess,
                                         {})
        return secret_reveal and unlock_success

    assert wait_until(test_initiator_events, network_wait)

    def test_mediator_events():
        assert not has_unlock_failure(app1)
        mediator_events = app1.wal.storage.get_events()
        unlock_success = search_for_item(mediator_events, EventUnlockSuccess,
                                         {})
        unlock_claim_success = search_for_item(mediator_events,
                                               EventUnlockClaimSuccess, {})
        return unlock_success and unlock_claim_success

    assert wait_until(test_mediator_events, network_wait)

    def test_target_events():
        assert not has_unlock_failure(app2)
        target_events = app2.wal.storage.get_events()
        return (search_for_item(target_events, SendSecretRequest, {})
                and search_for_item(target_events, SendSecretReveal, {}) and
                search_for_item(target_events, EventUnlockClaimSuccess, {}))

    assert wait_until(test_target_events, network_wait)
Beispiel #18
0
def run_test_regression_unfiltered_routes(raiden_network, token_addresses,
                                          settle_timeout, deposit):
    app0, app1, app2, app3, app4 = raiden_network
    token = token_addresses[0]
    registry_address = app0.raiden.default_registry.address

    # Topology:
    #
    #  0 -> 1 -> 2 -> 4
    #       |         ^
    #       +--> 3 ---+
    app_channels = [(app0, app1), (app1, app2), (app1, app3), (app3, app4),
                    (app2, app4)]

    open_and_wait_for_channels(app_channels, registry_address, token, deposit,
                               settle_timeout)
    transfer(initiator_app=app0,
             target_app=app4,
             token_address=token,
             amount=1,
             identifier=1)
Beispiel #19
0
def test_settled_lock():
    """ After a lock has it's secret revealed and a transfer happened, the lock
    cannot be used to net any value with the contract.
    """
    deposit = 100
    asset = sha3('test_settled_lock')[:20]
    amount = 30

    # pylint: disable=unbalanced-tuple-unpacking
    apps = create_sequential_network(num_nodes=4, deposit=deposit, asset=asset)

    # mediated transfer with the secret revealed
    transfer(apps[0], apps[3], asset, amount)

    # create the latest transfer
    direct_transfer(apps[0], apps[1], asset, amount)

    secret = ''  # need to get the secret
    attack_channel = channel(apps[2], apps[1], asset)
    secret_transfer = get_received_transfer(attack_channel, 0)
    last_transfer = get_received_transfer(attack_channel, 1)
    nettingcontract_address = attack_channel.nettingcontract_address

    # create a fake proof
    merkle_proof = attack_channel.our_state.locked.get_proof(secret_transfer)

    # call close giving the secret for a transfer that has being revealed
    apps[1].raiden.chain.close(
        asset,
        nettingcontract_address,
        apps[1].raiden.address,
        [last_transfer],
        [(merkle_proof, secret_transfer.lock, secret)],
    )

    # forward the block number to allow settle
    for _ in range(NettingChannelContract.settle_timeout):
        apps[2].raiden.chain.next_block()

    apps[1].raiden.chain.settle(asset, nettingcontract_address)
Beispiel #20
0
def test_cancel_transfer(raiden_chain, asset, deposit):
    app0, app1, app2 = raiden_chain  # pylint: disable=unbalanced-tuple-unpacking

    messages = setup_messages_cb()
    mlogger = MessageLogger()

    assert_synched_channels(channel(app0, app1, asset), deposit, [],
                            channel(app1, app0, asset), deposit, [])

    assert_synched_channels(channel(app1, app2, asset), deposit, [],
                            channel(app2, app1, asset), deposit, [])

    # drain the channel app1 -> app2
    amount = 80
    direct_transfer(app1, app2, asset, amount)

    assert_synched_channels(channel(app0, app1, asset), deposit, [],
                            channel(app1, app0, asset), deposit, [])

    assert_synched_channels(channel(app1, app2, asset), deposit - amount, [],
                            channel(app2, app1, asset), deposit + amount, [])

    # app1 -> app2 is the only available path and doens't have resource, app1
    # needs to send RefundTransfer to app0
    transfer(app0, app2, asset, 50)

    assert_synched_channels(channel(app0, app1, asset), deposit, [],
                            channel(app1, app0, asset), deposit, [])

    assert_synched_channels(channel(app1, app2, asset), deposit - amount, [],
                            channel(app2, app1, asset), deposit + amount, [])

    assert len(
        messages
    ) == 6  # DirectTransfer + MediatedTransfer + RefundTransfer + a Ack for each

    app1_messages = mlogger.get_node_messages(pex(app1.raiden.address),
                                              only='sent')

    assert isinstance(app1_messages[-1], RefundTransfer)
Beispiel #21
0
def test_settled_lock():
    """ After a lock has it's secret revealed and a transfer happened, the lock
    cannot be used to net any value with the contract.
    """
    deposit = 100
    asset = sha3('test_settled_lock')[:20]
    amount = 30

    # pylint: disable=unbalanced-tuple-unpacking
    apps = create_sequential_network(num_nodes=4, deposit=deposit, asset=asset)

    # mediated transfer with the secret revealed
    transfer(apps[0], apps[3], asset, amount)

    # create the latest transfer
    direct_transfer(apps[0], apps[1], asset, amount)

    secret = ''  # need to get the secret
    attack_channel = channel(apps[2], apps[1], asset)
    secret_transfer = get_received_transfer(attack_channel, 0)
    last_transfer = get_received_transfer(attack_channel, 1)
    nettingcontract_address = attack_channel.nettingcontract_address

    # create a fake proof
    merkle_proof = attack_channel.our_state.locked.get_proof(secret_transfer)

    # call close giving the secret for a transfer that has being revealed
    apps[1].raiden.chain.close(
        asset,
        nettingcontract_address,
        apps[1].raiden.address,
        [last_transfer],
        [(merkle_proof, secret_transfer.lock, secret)],
    )

    # forward the block number to allow settle
    for _ in range(NettingChannelContract.locked_time):
        apps[2].raiden.chain.next_block()

    apps[1].raiden.chain.settle(asset, nettingcontract_address)
def test_pfs_send_capacity_updates_during_mediated_transfer(
        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)
    token_network_registry_address = app0.raiden.default_registry.address
    token_network_address = views.get_token_network_address_by_token_address(
        chain_state, token_network_registry_address, token_address)

    # Mock send_text on the PFS room
    transport0 = app0.raiden.transport
    pfs_room_name = make_room_alias(transport0.chain_id,
                                    PATH_FINDING_BROADCASTING_ROOM)
    pfs_room = transport0._broadcast_rooms.get(pfs_room_name)
    # need to assert for mypy that pfs_room is not None
    assert isinstance(pfs_room, Room)
    pfs_room.send_text = MagicMock(spec=pfs_room.send_text)

    amount = PaymentAmount(10)
    secrethash = transfer(
        initiator_app=app0,
        target_app=app1,
        token_address=token_address,
        amount=amount,
        identifier=PaymentID(1),
        timeout=network_wait * number_of_nodes,
    )

    with block_timeout_for_transfer_by_secrethash(app1.raiden, secrethash):
        wait_assert(
            assert_succeeding_transfer_invariants,
            token_network_address,
            app0,
            deposit - amount,
            [],
            app1,
            deposit + amount,
            [],
        )

    # We expect one PFSCapacityUpdate when locking and one when unlocking
    assert pfs_room.send_text.call_count == 2
    assert "PFSCapacityUpdate" in str(pfs_room.send_text.call_args_list[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)
    token_network_registry_address = app0.raiden.default_registry.address
    token_network_address = views.get_token_network_address_by_token_address(
        chain_state, token_network_registry_address, token_address
    )

    amount = PaymentAmount(10)
    secrethash = transfer(
        initiator_app=app0,
        target_app=app2,
        token_address=token_address,
        amount=amount,
        identifier=PaymentID(1),
        timeout=network_wait * number_of_nodes,
    )

    with block_timeout_for_transfer_by_secrethash(app1.raiden, secrethash):
        wait_assert(
            assert_succeeding_transfer_invariants,
            token_network_address,
            app0,
            deposit - amount,
            [],
            app1,
            deposit + amount,
            [],
        )
    with block_timeout_for_transfer_by_secrethash(app1.raiden, secrethash):
        wait_assert(
            assert_succeeding_transfer_invariants,
            token_network_address,
            app1,
            deposit - amount,
            [],
            app2,
            deposit + amount,
            [],
        )
def run_test_node_can_settle_if_close_didnt_use_any_balance_proof(
    raiden_network,
    number_of_nodes,
    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
    transfer(
        initiator_app=app0,
        target_app=app1,
        token_address=token_address,
        amount=1,
        identifier=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,
        given_block_identifier='latest',
    )
    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,
        },
    )
def test_cancel_transfer(raiden_chain, token_addresses, deposit):
    """ 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  # pylint: disable=unbalanced-tuple-unpacking

    token = token_addresses[0]

    assert_synched_channels(
        channel(app0, app1, token), deposit, [],
        channel(app1, app0, token), deposit, []
    )

    assert_synched_channels(
        channel(app1, app2, token), deposit, [],
        channel(app2, app1, token), deposit, []
    )

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

    # drain the channel app1 -> app2
    identifier_drain = 2
    amount_drain = int(deposit * 0.8)
    direct_transfer(app1, app2, token, amount_drain, identifier_drain)

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

    assert_synched_channels(
        channel(app0, app1, token), deposit - amount_path, [],
        channel(app1, app0, token), deposit + amount_path, []
    )

    assert_synched_channels(
        channel(app1, app2, token), deposit - amount_path - amount_drain, [],
        channel(app2, app1, token), deposit + amount_path + amount_drain, []
    )

    # app0 -> app1 -> app2 is the only available path but the channel app1 ->
    # app2 doesnt have resources and needs to send a RefundTransfer down the
    # path
    identifier_refund = 3
    amount_refund = 50
    async_result = app0.raiden.mediated_transfer_async(
        token,
        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, MediatedTransfer) 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.hashlock == refund_message.lock.hashlock
    assert mediated_message.lock.expiration > refund_message.lock.expiration

    # Both channels have the amount locked because of the refund message
    assert_synched_channels(
        channel(app0, app1, token), deposit - amount_path, [refund_message.lock],
        channel(app1, app0, token), deposit + amount_path, [mediated_message.lock],
    )

    assert_synched_channels(
        channel(app1, app2, token), deposit - amount_path - amount_drain, [],
        channel(app2, app1, token), deposit + amount_path + amount_drain, []
    )
Beispiel #26
0
def run_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
    transfer(
        initiator_app=app0,
        target_app=app3,
        token_address=token_address,
        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
    transfer(
        initiator_app=app2,
        target_app=app3,
        token_address=token_address,
        amount=amount_drain,
        identifier=identifier_drain,
        timeout=network_wait,
    )

    with gevent.Timeout(network_wait):
        wait_assert(
            assert_synced_channel_state,
            token_network_identifier,
            app0,
            deposit - amount_path,
            [],
            app1,
            deposit + amount_path,
            [],
        )
    with gevent.Timeout(network_wait):
        wait_assert(
            assert_synced_channel_state,
            token_network_identifier,
            app1,
            deposit - amount_path,
            [],
            app2,
            deposit + amount_path,
            [],
        )
    with gevent.Timeout(network_wait):
        wait_assert(
            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
    payment_status = app0.raiden.mediated_transfer_async(
        token_network_identifier,
        amount_refund,
        app3.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)

    # Lock structures with the correct amount

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

    send_refund1 = raiden_events_search_for_item(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_search_for_item(
        app1.raiden,
        SendLockedTransfer,
        {'transfer': {
            'lock': {
                'amount': amount_refund
            }
        }},
    )
    assert send_locked2

    send_refund2 = raiden_events_search_for_item(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
    with gevent.Timeout(network_wait):
        wait_assert(
            assert_synced_channel_state,
            token_network_identifier,
            app0,
            deposit - amount_path,
            [lock1],
            app1,
            deposit + amount_path,
            [refund_lock1],
        )
    with gevent.Timeout(network_wait):
        wait_assert(
            assert_synced_channel_state,
            token_network_identifier,
            app1,
            deposit - amount_path,
            [lock2],
            app2,
            deposit + amount_path,
            [refund_lock2],
        )
    with gevent.Timeout(network_wait):
        wait_assert(
            assert_synced_channel_state,
            token_network_identifier,
            app2,
            deposit - amount_path - amount_drain,
            [],
            app3,
            deposit + amount_path + amount_drain,
            [],
        )
Beispiel #27
0
def run_test_refund_messages(raiden_chain, token_addresses, deposit,
                             network_wait):
    # 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
    transfer(
        initiator_app=app1,
        target_app=app2,
        token_address=token_address,
        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

    with gevent.Timeout(network_wait):
        wait_assert(
            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
    with gevent.Timeout(network_wait):
        wait_assert(
            assert_synced_channel_state,
            token_network_identifier,
            app1,
            0,
            [],
            app2,
            deposit * 2,
            [],
        )
Beispiel #28
0
def run_test_different_view_of_last_bp_during_unlock(
    raiden_chain,
    number_of_nodes,
    token_addresses,
    deposit,
    network_wait,
    retry_timeout,
    blockchain_type,
):
    """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
    transfer(
        initiator_app=app0,
        target_app=app2,
        token_address=token_address,
        amount=amount_path,
        identifier=identifier_path,
        timeout=network_wait * number_of_nodes,
    )

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

    with gevent.Timeout(network_wait):
        wait_assert(
            assert_synced_channel_state,
            token_network_identifier,
            app0,
            deposit - amount_path,
            [],
            app1,
            deposit + amount_path,
            [],
        )
    with gevent.Timeout(network_wait):
        wait_assert(
            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
    with gevent.Timeout(network_wait):
        wait_assert(
            assert_synced_channel_state,
            token_network_identifier,
            app0,
            deposit - amount_path,
            [lock],
            app1,
            deposit + amount_path,
            [refund_lock],
        )
    with gevent.Timeout(network_wait):
        wait_assert(
            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,
    )

    timeout = 30 if blockchain_type == 'parity' else 10
    with gevent.Timeout(timeout):
        unlock_app0 = wait_for_state_change(
            app0.raiden,
            ContractReceiveChannelBatchUnlock,
            {'participant': app0.raiden.address},
            retry_timeout,
        )
    assert unlock_app0.returned_tokens == 50
    with gevent.Timeout(timeout):
        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
Beispiel #29
0
def run_test_refund_transfer(
    raiden_chain,
    number_of_nodes,
    token_addresses,
    deposit,
    network_wait,
    retry_timeout,
):
    """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
    transfer(
        initiator_app=app0,
        target_app=app2,
        token_address=token_address,
        amount=amount_path,
        identifier=identifier_path,
        timeout=network_wait * number_of_nodes,
    )

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

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

    with gevent.Timeout(network_wait):
        wait_assert(
            assert_synced_channel_state,
            token_network_identifier,
            app0,
            deposit - amount_path,
            [],
            app1,
            deposit + amount_path,
            [],
        )
    with gevent.Timeout(network_wait):
        wait_assert(
            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
    with gevent.Timeout(network_wait):
        wait_assert(
            assert_synced_channel_state,
            token_network_identifier,
            app0,
            deposit - amount_path,
            [lock],
            app1,
            deposit + amount_path,
            [refund_lock],
        )
    with gevent.Timeout(network_wait):
        wait_assert(
            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
Beispiel #30
0
def test_cancel_transfer(raiden_chain, asset, deposit):

    app0, app1, app2, app3 = raiden_chain  # pylint: disable=unbalanced-tuple-unpacking

    messages = setup_messages_cb()
    mlogger = MessageLogger()

    assert_synched_channels(
        channel(app0, app1, asset), deposit, [],
        channel(app1, app0, asset), deposit, []
    )

    assert_synched_channels(
        channel(app1, app2, asset), deposit, [],
        channel(app2, app1, asset), deposit, []
    )

    assert_synched_channels(
        channel(app2, app3, asset), deposit, [],
        channel(app3, app2, asset), deposit, []
    )

    assert_synched_channels(
        channel(app0, app1, asset), deposit, [],
        channel(app1, app0, asset), deposit, []
    )

    # drain the channel app1 -> app2
    amount12 = 50
    direct_transfer(app1, app2, asset, amount12)

    # drain the channel app2 -> app3
    amount23 = 80
    direct_transfer(app2, app3, asset, amount23)

    assert_synched_channels(
        channel(app1, app2, asset), deposit - amount12, [],
        channel(app2, app1, asset), deposit + amount12, []
    )

    assert_synched_channels(
        channel(app2, app3, asset), deposit - amount23, [],
        channel(app3, app2, asset), deposit + amount23, []
    )

    # app1 -> app3 is the only available path but app2 -> app3 doesnt have
    # resources and needs to send a RefundTransfer down the path
    transfer(app0, app3, asset, 50)

    assert_synched_channels(
        channel(app0, app1, asset), deposit, [],
        channel(app1, app0, asset), deposit, []
    )

    assert_synched_channels(
        channel(app1, app2, asset), deposit - amount12, [],
        channel(app2, app1, asset), deposit + amount12, []
    )

    assert_synched_channels(
        channel(app2, app3, asset), deposit - amount23, [],
        channel(app3, app2, asset), deposit + amount23, []
    )

    assert len(messages) == 12  # DT + DT + SMT + MT + RT + RT + ACKs

    app1_messages = mlogger.get_node_messages(pex(app1.raiden.address), only='sent')
    assert isinstance(app1_messages[-1], RefundTransfer)

    app2_messages = mlogger.get_node_messages(pex(app2.raiden.address), only='sent')
    assert isinstance(app2_messages[-1], RefundTransfer)
Beispiel #31
0
def test_cancel_transfer(raiden_chain, token_addresses, deposit):
    """ 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  # pylint: disable=unbalanced-tuple-unpacking

    token = token_addresses[0]

    assert_synched_channels(channel(app0, app1, token), deposit, [],
                            channel(app1, app0, token), deposit, [])

    assert_synched_channels(channel(app1, app2, token), deposit, [],
                            channel(app2, app1, token), deposit, [])

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

    # drain the channel app1 -> app2
    identifier_drain = 2
    amount_drain = int(deposit * 0.8)
    direct_transfer(app1, app2, token, amount_drain, identifier_drain)

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

    assert_synched_channels(channel(app0, app1,
                                    token), deposit - amount_path, [],
                            channel(app1, app0, token), deposit + amount_path,
                            [])

    assert_synched_channels(channel(app1, app2, token),
                            deposit - amount_path - amount_drain, [],
                            channel(app2, app1, token),
                            deposit + amount_path + amount_drain, [])

    # app0 -> app1 -> app2 is the only available path but the channel app1 ->
    # app2 doesnt have resources and needs to send a RefundTransfer down the
    # path
    identifier_refund = 3
    amount_refund = 50
    async_result = app0.raiden.mediated_transfer_async(
        token,
        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, MediatedTransfer)
                            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.hashlock == refund_message.lock.hashlock
    assert mediated_message.lock.expiration > refund_message.lock.expiration

    # Both channels have the amount locked because of the refund message
    assert_synched_channels(
        channel(app0, app1, token),
        deposit - amount_path,
        [refund_message.lock],
        channel(app1, app0, token),
        deposit + amount_path,
        [mediated_message.lock],
    )

    assert_synched_channels(channel(app1, app2, token),
                            deposit - amount_path - amount_drain, [],
                            channel(app2, app1, token),
                            deposit + amount_path + amount_drain, [])
Beispiel #32
0
def test_recovery_unhappy_case(
    raiden_network,
    number_of_nodes,
    deposit,
    token_addresses,
    network_wait,
    skip_if_not_udp,  # pylint: disable=unused-argument
    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 identifier in range(spent_amount):
        transfer(
            initiator_app=app0,
            target_app=app2,
            token_address=token_address,
            amount=amount,
            identifier=identifier,
            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,
        default_service_registry=app0.raiden.default_service_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 search_for_item(
        state_changes,
        ContractReceiveChannelSettled,
        {
            "token_network_identifier": token_network_identifier,
            "channel_identifier": channel01.identifier,
        },
    )
Beispiel #33
0
def test_recovery_happy_case(
        raiden_network,
        number_of_nodes,
        deposit,
        token_addresses,
        network_wait,
        skip_if_not_udp,  # pylint: disable=unused-argument
):
    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
    identifier = 0
    for identifier in range(spent_amount):
        transfer_and_assert_path(
            path=raiden_network,
            token_address=token_address,
            amount=amount,
            identifier=identifier,
            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 = WaitForMessage()

    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,
        default_service_registry=app0.raiden.default_service_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)

    transfer(
        initiator_app=app2,
        target_app=app0_restart,
        token_address=token_address,
        amount=amount,
        identifier=create_default_identifier(),
        timeout=network_wait * number_of_nodes * 2,
    )
    transfer(
        initiator_app=app0_restart,
        target_app=app2,
        token_address=token_address,
        amount=amount,
        identifier=create_default_identifier(),
        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,
        [],
    )