Пример #1
0
def test_settlement(raiden_network, settle_timeout):
    app0, app1 = raiden_network  # pylint: disable=unbalanced-tuple-unpacking

    setup_messages_cb()

    asset_manager0 = app0.raiden.managers_by_asset_address.values()[0]
    asset_manager1 = app1.raiden.managers_by_asset_address.values()[0]

    chain0 = app0.raiden.chain

    channel0 = asset_manager0.partneraddress_channel[app1.raiden.address]
    channel1 = asset_manager1.partneraddress_channel[app0.raiden.address]

    balance0 = channel0.balance
    balance1 = channel1.balance

    amount = 10
    expiration = 10
    secret = 'secret'
    hashlock = sha3(secret)

    assert app1.raiden.address in asset_manager0.partneraddress_channel
    assert asset_manager0.asset_address == asset_manager1.asset_address
    assert channel0.external_state.netting_channel.address == channel1.external_state.netting_channel.address

    transfermessage = channel0.create_lockedtransfer(amount, expiration, hashlock)
    app0.raiden.sign(transfermessage)
    channel0.register_transfer(transfermessage)
    channel1.register_transfer(transfermessage)

    assert_synched_channels(
        channel0, balance0, [transfermessage.lock],
        channel1, balance1, []
    )

    # Bob learns the secret, but Alice did not send a signed updated balance to
    # reflect this Bob wants to settle

    # get proof, that locked transfermessage was in merkle tree, with locked.root
    merkle_proof = channel1.our_state.locked.get_proof(transfermessage)
    root = channel1.our_state.locked.root
    assert check_proof(merkle_proof, root, sha3(transfermessage.lock.as_bytes))

    channel0.external_state.netting_channel.close(
        app0.raiden.address,
        transfermessage,
        None,
    )

    unlocked = [(merkle_proof, transfermessage.lock.as_bytes, secret)]

    channel0.external_state.netting_channel.unlock(
        app0.raiden.address,
        unlocked,
    )

    for _ in range(settle_timeout):
        chain0.next_block()

    channel0.external_state.netting_channel.settle()
Пример #2
0
def test_settlement(raiden_network, settle_timeout):
    app0, app1 = raiden_network  # pylint: disable=unbalanced-tuple-unpacking

    setup_messages_cb()

    asset_manager0 = app0.raiden.managers_by_asset_address.values()[0]
    asset_manager1 = app1.raiden.managers_by_asset_address.values()[0]

    chain0 = app0.raiden.chain

    channel0 = asset_manager0.partneraddress_channel[app1.raiden.address]
    channel1 = asset_manager1.partneraddress_channel[app0.raiden.address]

    balance0 = channel0.balance
    balance1 = channel1.balance

    amount = 10
    expiration = 5
    secret = 'secret'
    hashlock = sha3(secret)

    assert app1.raiden.address in asset_manager0.partneraddress_channel
    assert asset_manager0.asset_address == asset_manager1.asset_address
    assert channel0.external_state.netting_channel.address == channel1.external_state.netting_channel.address

    transfermessage = channel0.create_lockedtransfer(amount, expiration, hashlock)
    app0.raiden.sign(transfermessage)
    channel0.register_transfer(transfermessage)
    channel1.register_transfer(transfermessage)

    assert_synched_channels(
        channel0, balance0, [transfermessage.lock],
        channel1, balance1, []
    )

    # Bob learns the secret, but Alice did not send a signed updated balance to
    # reflect this Bob wants to settle

    # get proof, that locked transfermessage was in merkle tree, with locked.root
    merkle_proof = channel1.our_state.locked.get_proof(transfermessage)
    root = channel1.our_state.locked.root
    assert check_proof(merkle_proof, root, sha3(transfermessage.lock.as_bytes))

    channel0.external_state.netting_channel.close(
        app0.raiden.address,
        transfermessage,
        None,
    )

    unlocked = [(merkle_proof, transfermessage.lock.as_bytes, secret)]

    channel0.external_state.netting_channel.unlock(
        app0.raiden.address,
        unlocked,
    )

    for _ in range(settle_timeout):
        chain0.next_block()

    channel0.external_state.netting_channel.settle()
Пример #3
0
def test_webui():  # pylint: disable=too-many-locals
    num_assets = 3
    num_nodes = 10

    assets_addresses = [
        sha3('webui:asset:{}'.format(number))[:20]
        for number in range(num_assets)
    ]

    private_keys = [
        sha3('webui:{}'.format(position))
        for position in range(num_nodes)
    ]

    BlockChainServiceMock._instance = True
    blockchain_service= BlockChainServiceMock(None, MOCK_REGISTRY_ADDRESS)
    # overwrite the instance
    BlockChainServiceMock._instance = blockchain_service # pylint: disable=redefined-variable-type

    registry = blockchain_service.registry(MOCK_REGISTRY_ADDRESS)

    for asset in assets_addresses:
        registry.add_asset(asset)

    channels_per_node = 2
    deposit = 100
    app_list = create_network(
        private_keys,
        assets_addresses,
        MOCK_REGISTRY_ADDRESS,
        channels_per_node,
        deposit,
        DEFAULT_SETTLE_TIMEOUT,
        UDPTransport,
        BlockChainServiceMock
    )
    app0 = app_list[0]

    addresses = [
        app.raiden.address.encode('hex')
        for app in app_list
        if app != app_list[0]
    ]

    print '\nCreated nodes: \n',
    for node in addresses:
        print node

    setup_messages_cb()

    app0_assets = getattr(app0.raiden.api, 'assets')
    print '\nAvailable assets:'
    for asset in app0_assets:
        print asset.encode('hex')
    print '\n'

    wamp = WAMPRouter(app0.raiden, 8080, ['channel', 'test'])
    wamp.run()
Пример #4
0
def test_mediated_transfer():
    app_list = create_network(num_nodes=10, num_assets=1, channels_per_node=2)
    app0 = app_list[0]
    setup_messages_cb()

    am0 = app0.raiden.assetmanagers.values()[0]

    # search for a path of length=2 A > B > C
    num_hops = 2
    source = app0.raiden.address

    path_list = am0.channelgraph.get_paths_of_length(source, num_hops)
    assert len(path_list)

    for path in path_list:
        assert len(path) == num_hops + 1
        assert path[0] == source

    path = path_list[0]
    target = path[-1]
    assert path in am0.channelgraph.get_shortest_paths(source, target)
    assert min(len(p) for p in am0.channelgraph.get_shortest_paths(source, target)) == num_hops + 1

    ams_by_address = dict(
        (app.raiden.address, app.raiden.assetmanagers)
        for app in app_list
    )

    # addresses
    hop1, hop2, hop3 = path

    # asset
    asset_address = am0.asset_address

    # channels
    c_ab = ams_by_address[hop1][asset_address].channels[hop2]
    c_ba = ams_by_address[hop2][asset_address].channels[hop1]
    c_bc = ams_by_address[hop2][asset_address].channels[hop3]
    c_cb = ams_by_address[hop3][asset_address].channels[hop2]

    # initial channel balances
    b_ab = c_ab.our_state.balance
    b_ba = c_ba.our_state.balance
    b_bc = c_bc.our_state.balance
    b_cb = c_cb.our_state.balance

    amount = 10

    app0.raiden.api.transfer(asset_address, amount, target)

    gevent.sleep(1.)

    # check
    assert b_ab - amount == c_ab.our_state.balance
    assert b_ba + amount == c_ba.our_state.balance
    assert b_bc - amount == c_bc.our_state.balance
    assert b_cb + amount == c_cb.our_state.balance
Пример #5
0
def test_ping_dropped_message():
    apps = create_network(
        num_nodes=2,
        num_assets=0,
        channels_per_node=0,
        transport_class=UnreliableTransport,
    )
    app0, app1 = apps  # pylint: disable=unbalanced-tuple-unpacking

    # mock transport with packet loss, every 3nd is lost, starting with first message
    UnreliableTransport.droprate = 3
    RaidenProtocol.try_interval = 0.1  # for fast tests
    RaidenProtocol.repeat_messages = True

    messages = setup_messages_cb()
    UnreliableTransport.network.counter = 0

    ping = Ping(nonce=0)
    app0.raiden.sign(ping)
    app0.raiden.protocol.send(app1.raiden.address, ping)
    gevent.sleep(1)

    assert len(messages) == 3  # Ping(dropped), Ping, Ack

    for i in [0, 1]:
        assert decode(messages[i]) == ping

    for i in [2]:
        decoded = decode(messages[i])
        assert isinstance(decoded, Ack)

    assert decoded.echo == ping.hash

    # try failing Ack
    messages = setup_messages_cb()
    assert not messages

    UnreliableTransport.network.counter = 2  # first message sent, 2nd dropped
    ping = Ping(nonce=0)
    app0.raiden.sign(ping)
    app0.raiden.protocol.send(app1.raiden.address, ping)
    gevent.sleep(1)

    for message in messages:
        print decode(message)

    assert len(messages) == 4  # Ping, Ack(dropped), Ping, Ack
    for i in [0, 2]:
        assert decode(messages[i]) == ping
    for i in [1, 3]:
        decoded = decode(messages[i])
        assert isinstance(decoded, Ack)
    assert decoded.echo == ping.hash

    RaidenProtocol.repeat_messages = False
Пример #6
0
def test_webui():  # pylint: disable=too-many-locals
    num_assets = 3
    num_nodes = 10

    assets_addresses = [
        sha3('webui:asset:{}'.format(number))[:20]
        for number in range(num_assets)
    ]

    private_keys = [
        sha3('webui:{}'.format(position)) for position in range(num_nodes)
    ]

    BlockChainServiceMock._instance = True
    blockchain_service = BlockChainServiceMock(None, MOCK_REGISTRY_ADDRESS)
    # overwrite the instance
    BlockChainServiceMock._instance = blockchain_service  # pylint: disable=redefined-variable-type

    registry = blockchain_service.registry(MOCK_REGISTRY_ADDRESS)

    for asset in assets_addresses:
        registry.add_asset(asset)

    channels_per_node = 2
    deposit = 100
    app_list = create_network(private_keys, assets_addresses,
                              MOCK_REGISTRY_ADDRESS, channels_per_node,
                              deposit, DEFAULT_SETTLE_TIMEOUT, UDPTransport,
                              BlockChainServiceMock)
    app0 = app_list[0]

    addresses = [
        app.raiden.address.encode('hex') for app in app_list
        if app != app_list[0]
    ]

    print '\nCreated nodes: \n',
    for node in addresses:
        print node

    setup_messages_cb()

    app0_assets = getattr(app0.raiden.api, 'assets')
    print '\nAvailable assets:'
    for asset in app0_assets:
        print asset.encode('hex')
    print '\n'

    wamp = WAMPRouter(app0.raiden, 8080, ['channel', 'test'])
    wamp.run()
Пример #7
0
def test_receive_mediatedtransfer_invalid_address(raiden_network,
                                                  private_keys):
    alice_app = raiden_network[0]
    setup_messages_cb()

    graph = alice_app.raiden.channelgraphs.values()[0]
    token_address = graph.token_address

    mt_helper = MediatedTransferTestHelper(raiden_network, graph)
    initiator_address = alice_app.raiden.address
    path = mt_helper.get_paths_of_length(initiator_address, 2)

    alice_address, bob_address, charlie_address = path
    amount = 10
    result = alice_app.raiden.transfer_async(
        token_address,
        amount,
        charlie_address,
    )

    assert result.wait(timeout=10)
    gevent.sleep(1.)

    # and now send one more mediated transfer with the same nonce, simulating
    # an out-of-order/resent message that arrives late
    locksroot = HASH
    lock = Lock(amount, 1, locksroot)
    identifier = create_default_identifier(
        alice_app.raiden.address,
        graph.token_address,
        charlie_address,
    )
    mediated_transfer = MediatedTransfer(identifier=identifier,
                                         nonce=1,
                                         token=token_address,
                                         transferred_amount=amount,
                                         recipient=bob_address,
                                         locksroot=locksroot,
                                         lock=lock,
                                         target=charlie_address,
                                         initiator=initiator_address,
                                         fee=0)
    alice_key = PrivateKey(private_keys[0])
    target_app = None
    for app in raiden_network:
        if app.raiden.address not in path:
            target_app = app
            break
    sign_and_send(mediated_transfer, alice_key, alice_address, target_app)
Пример #8
0
def test_healthcheck_with_normal_peer(raiden_network):
    app0, app1 = raiden_network  # pylint: disable=unbalanced-tuple-unpacking
    messages = setup_messages_cb()

    asset_manager0 = app0.raiden.managers_by_asset_address.values()[0]
    asset_manager1 = app1.raiden.managers_by_asset_address.values()[0]

    max_unresponsive_time = app0.raiden.config['max_unresponsive_time']

    assert asset_manager0.asset_address == asset_manager1.asset_address
    assert app1.raiden.address in asset_manager0.partneraddress_channel

    amount = 10
    app0.raiden.api.transfer(
        asset_manager0.asset_address,
        amount,
        target=app1.raiden.address,
    )

    gevent.sleep(max_unresponsive_time)
    assert asset_manager0.channelgraph.has_path(
        app0.raiden.address,
        app1.raiden.address
    )

    # At this point we should have sent a direct transfer and got back the ack
    # and gotten at least 1 ping - ack for a normal healthcheck
    assert len(messages) >= 4  # DirectTransfer, Ack, Ping, Ack
    assert isinstance(decode(messages[0]), DirectTransfer)
    assert isinstance(decode(messages[1]), Ack)
    assert isinstance(decode(messages[2]), Ping)
    assert isinstance(decode(messages[3]), Ack)
def test_healthcheck_with_normal_peer(raiden_network, token_addresses):
    app0, app1 = raiden_network  # pylint: disable=unbalanced-tuple-unpacking
    messages = setup_messages_cb()

    token_address = token_addresses[0]

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

    graph0 = app0.raiden.token_to_channelgraph[token_address]
    graph1 = app1.raiden.token_to_channelgraph[token_address]

    # check the nodes have a channel
    assert graph0.token_address == graph1.token_address
    assert address1 in graph0.partneraddress_to_channel
    assert address0 in graph1.partneraddress_to_channel

    # check both have started the healthcheck
    assert address0 in app1.raiden.protocol.addresses_events
    assert address1 in app0.raiden.protocol.addresses_events

    # wait for the healthcheck task to send a ping
    gevent.sleep(app0.raiden.protocol.nat_keepalive_timeout)
    gevent.sleep(app1.raiden.protocol.nat_keepalive_timeout)

    decoded_messages = [decode(m) for m in set(messages)]
    ping_messages = get_messages_by_type(decoded_messages, Ping)

    assert ping_messages
Пример #10
0
def test_ping(raiden_network):
    app0, app1 = raiden_network  # pylint: disable=unbalanced-tuple-unpacking

    messages = setup_messages_cb()

    ping_message = Ping(nonce=0)
    app0.raiden.sign(ping_message)
    ping_encoded = ping_message.encode()

    async_result = app0.raiden.protocol.send_raw_with_result(
        ping_encoded,
        app1.raiden.address,
    )
    assert async_result.wait(2), "The message was not acknowledged"

    expected_echohash = sha3(ping_encoded + app1.raiden.address)

    messages_decoded = [decode(m) for m in messages]
    ack_message = next(
        decoded for decoded in messages_decoded
        if isinstance(decoded, Ack) and decoded.echo == expected_echohash)

    # the ping message was sent and acknowledged
    assert ping_encoded in messages
    assert ack_message
Пример #11
0
def test_udp_ping_pong(raiden_network):
    app0, app1 = raiden_network  # pylint: disable=unbalanced-tuple-unpacking

    messages = setup_messages_cb()

    ping_message = Ping(nonce=0)
    app0.raiden.sign(ping_message)
    ping_encoded = ping_message.encode()

    messageid = ('ping', ping_message.nonce, app1.raiden.address)
    async_result = app0.raiden.protocol.maybe_sendraw_with_result(
        app1.raiden.address,
        ping_encoded,
        messageid,
    )
    assert async_result.wait(2), 'The message was not processed'

    messages_decoded = [decode(m) for m in messages]
    processed_message = next(
        pong for pong in messages_decoded
        if isinstance(pong, Pong) and pong.nonce == ping_message.nonce)

    # the ping message was sent and processed
    assert ping_encoded in messages
    assert processed_message
def test_healthcheck_with_normal_peer(raiden_network):
    app0, app1 = raiden_network  # pylint: disable=unbalanced-tuple-unpacking
    messages = setup_messages_cb()

    graph0 = app0.raiden.token_to_channelgraph.values()[0]
    graph1 = app1.raiden.token_to_channelgraph.values()[0]

    assert graph0.token_address == graph1.token_address
    assert app1.raiden.address in graph0.partneraddress_to_channel

    amount = 10
    target = app1.raiden.address
    result = app0.raiden.direct_transfer_async(
        graph0.token_address,
        amount,
        target,
        identifier=1,
    )
    assert result.wait(timeout=10)

    assert graph0.has_path(
        app0.raiden.address,
        app1.raiden.address
    )

    # At this point we should have sent a direct transfer and got back the ack
    # and gotten at least 1 ping - ack for a normal healthcheck
    decoded_messages = [decode(m) for m in unique(messages)]
    direct_messages = get_messages_by_type(decoded_messages, DirectTransfer)

    assert len(direct_messages) == 1
    assert_ack_for(app1, direct_messages[0], decoded_messages)

    ping_messages = get_messages_by_type(decoded_messages, Ping)
    assert ping_messages
Пример #13
0
def test_healthcheck_with_normal_peer(raiden_network):
    app0, app1 = raiden_network  # pylint: disable=unbalanced-tuple-unpacking
    messages = setup_messages_cb()

    asset_manager0 = app0.raiden.managers_by_asset_address.values()[0]
    asset_manager1 = app1.raiden.managers_by_asset_address.values()[0]

    max_unresponsive_time = app0.raiden.config['max_unresponsive_time']

    assert asset_manager0.asset_address == asset_manager1.asset_address
    assert app1.raiden.address in asset_manager0.partneraddress_channel

    amount = 10
    app0.raiden.api.transfer(
        asset_manager0.asset_address,
        amount,
        target=app1.raiden.address,
    )

    gevent.sleep(max_unresponsive_time)
    assert asset_manager0.channelgraph.has_path(
        app0.raiden.address,
        app1.raiden.address
    )

    # At this point we should have sent a direct transfer and got back the ack
    # and gotten at least 1 ping - ack for a normal healthcheck
    assert len(messages) >= 4  # DirectTransfer, Ack, Ping, Ack
    assert isinstance(decode(messages[0]), DirectTransfer)
    assert isinstance(decode(messages[1]), Ack)
    assert isinstance(decode(messages[2]), Ping)
    assert isinstance(decode(messages[3]), Ack)
Пример #14
0
def test_ping_unreachable(raiden_network):
    app0, app1 = raiden_network  # pylint: disable=unbalanced-tuple-unpacking

    UnreliableTransport.droprate = 1  # drop everything to force disabling of re-sends
    app0.raiden.protocol.retry_interval = 0.1  # for fast tests

    messages = setup_messages_cb()
    UnreliableTransport.network.counter = 0

    ping_message = Ping(nonce=0)
    app0.raiden.sign(ping_message)
    ping_encoded = ping_message.encode()

    async_result = app0.raiden.protocol.send_raw_with_result(
        ping_encoded,
        app1.raiden.address,
    )

    assert async_result.wait(
        2) is None, "The message was dropped, it can't be acknowledged"

    # Raiden node will start pinging as soon as a new channel
    #  is established. We need to test if
    #  a) there is our original message in the queue
    #  b) there are only Ping message types in
    messages_decoded = [decode(m) for m in messages]
    assert ping_message in messages_decoded
    for message in messages_decoded:
        assert isinstance(message, Ping)
Пример #15
0
def test_healthcheck_with_normal_peer(raiden_network):
    app0, app1 = raiden_network  # pylint: disable=unbalanced-tuple-unpacking
    messages = setup_messages_cb()

    graph0 = app0.raiden.channelgraphs.values()[0]
    graph1 = app1.raiden.channelgraphs.values()[0]

    max_unresponsive_time = app0.raiden.config['max_unresponsive_time']

    assert graph0.token_address == graph1.token_address
    assert app1.raiden.address in graph0.partneraddress_channel

    amount = 10
    target = app1.raiden.address
    result = app0.raiden.transfer_async(
        graph0.token_address,
        amount,
        target,
    )
    assert result.wait(timeout=10)

    gevent.sleep(max_unresponsive_time)
    assert graph0.has_path(
        app0.raiden.address,
        app1.raiden.address
    )

    # At this point we should have sent a direct transfer and got back the ack
    # and gotten at least 1 ping - ack for a normal healthcheck
    assert len(messages) >= 4  # DirectTransfer, Ack, Ping, Ack
    assert isinstance(decode(messages[0]), DirectTransfer)
    assert isinstance(decode(messages[1]), Ack)
    assert isinstance(decode(messages[2]), Ping)
    assert isinstance(decode(messages[3]), Ack)
Пример #16
0
def test_mediated_transfer(raiden_network):
    alice_app = raiden_network[0]
    messages = setup_messages_cb()

    graph = alice_app.raiden.channelgraphs.values()[0]
    token_address = graph.token_address
    mt_helper = MediatedTransferTestHelper(raiden_network, graph)

    initiator_address = alice_app.raiden.address
    path = mt_helper.get_paths_of_length(initiator_address, 2)
    mt_helper.assert_path_in_shortest_paths(path, initiator_address, 2)
    alice_address, bob_address, charlie_address = path

    # channels (alice <-> bob <-> charlie)
    channel_ab = mt_helper.get_channel(alice_address, bob_address)
    channel_ba = mt_helper.get_channel(bob_address, alice_address)
    channel_bc = mt_helper.get_channel(bob_address, charlie_address)
    channel_cb = mt_helper.get_channel(charlie_address, bob_address)

    initial_balance_ab = channel_ab.balance
    initial_balance_ba = channel_ba.balance
    initial_balance_bc = channel_bc.balance
    initial_balance_cb = channel_cb.balance

    amount = 10

    result = alice_app.raiden.transfer_async(
        token_address,
        amount,
        charlie_address,
    )

    # check for invitation ping
    assert len(messages) == 2  # Ping, Ack
    ping_message = decode(messages[0])
    assert isinstance(ping_message, Ping)
    decoded = decode(messages[1])
    assert isinstance(decoded, Ack)
    assert decoded.echo == sha3(ping_message.encode() + charlie_address)

    assert channel_ab.locked == amount

    # Cannot assert the intermediary state of the channels since the code is
    # concurrently executed.
    # assert channel_ba.outstanding == amount
    # assert channel_bc.locked == amount
    # assert channel_cb.outstanding == amount

    assert result.wait(timeout=10)
    gevent.sleep(.1)  # wait for the other nodes to sync

    # check that transfer messages were added
    assert len(messages) == 22  # Ping, Ack + tranfer messages
    # make sure that the mediated transfer is sent after the invitation ping
    assert isinstance(decode(messages[2]), MediatedTransfer)

    assert initial_balance_ab - amount == channel_ab.balance
    assert initial_balance_ba + amount == channel_ba.balance
    assert initial_balance_bc - amount == channel_bc.balance
    assert initial_balance_cb + amount == channel_cb.balance
Пример #17
0
def test_ping(raiden_network):
    app0, app1 = raiden_network  # pylint: disable=unbalanced-tuple-unpacking

    messages = setup_messages_cb()

    ping_message = Ping(nonce=0)
    app0.raiden.sign(ping_message)
    ping_encoded = ping_message.encode()

    async_result = app0.raiden.protocol.send_raw_with_result(
        ping_encoded,
        app1.raiden.address,
    )
    assert async_result.wait(2), 'The message was not processed'

    expected_messageid = messageid_from_data(ping_encoded, app1.raiden.address)
    messages_decoded = [decode(m) for m in messages]
    processed_message = next(
        decoded
        for decoded in messages_decoded
        if isinstance(decoded, Processed) and
        decoded.processed_message_identifier == expected_messageid
    )

    # the ping message was sent and processed
    assert ping_encoded in messages
    assert processed_message
Пример #18
0
def test_healthcheck_with_normal_peer(raiden_network, token_addresses):
    app0, app1 = raiden_network  # pylint: disable=unbalanced-tuple-unpacking
    messages = setup_messages_cb()

    token_address = token_addresses[0]

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

    graph0 = app0.raiden.token_to_channelgraph[token_address]
    graph1 = app1.raiden.token_to_channelgraph[token_address]

    # check the nodes have a channel
    assert graph0.token_address == graph1.token_address
    assert address1 in graph0.partneraddress_to_channel
    assert address0 in graph1.partneraddress_to_channel

    # check both have started the healthcheck
    assert address0 in app1.raiden.protocol.addresses_events
    assert address1 in app0.raiden.protocol.addresses_events

    # wait for the healthcheck task to send a ping
    gevent.sleep(app0.raiden.protocol.nat_keepalive_timeout)
    gevent.sleep(app1.raiden.protocol.nat_keepalive_timeout)

    decoded_messages = [decode(m) for m in set(messages)]
    ping_messages = get_messages_by_type(decoded_messages, Ping)

    assert ping_messages
Пример #19
0
def test_receive_mediatedtransfer_outoforder(raiden_network, private_keys):
    alice_app = raiden_network[0]
    messages = setup_messages_cb()

    graph = alice_app.raiden.channelgraphs.values()[0]
    token_address = graph.token_address

    mt_helper = MediatedTransferTestHelper(raiden_network, graph)
    initiator_address = alice_app.raiden.address
    path = mt_helper.get_paths_of_length(initiator_address, 2)

    # make sure we have no messages before the transfer
    assert len(messages) == 0

    alice_address, bob_address, charlie_address = path
    amount = 10
    result = alice_app.raiden.transfer_async(
        token_address,
        amount,
        charlie_address,
    )

    # check for invitation ping
    assert len(messages) == 2  # Ping, Ack
    ping_message = decode(messages[0])
    assert isinstance(ping_message, Ping)
    decoded = decode(messages[1])
    assert isinstance(decoded, Ack)
    assert decoded.echo == sha3(ping_message.encode() + charlie_address)

    assert result.wait(timeout=10)
    gevent.sleep(1.)

    # check that transfer messages were added
    assert len(messages) == 22  # Ping, Ack + tranfer messages
    # make sure that the mediated transfer is sent after the invitation ping
    assert isinstance(decode(messages[2]), MediatedTransfer)

    # and now send one more mediated transfer with the same nonce, simulating
    # an out-of-order/resent message that arrives late
    locksroot = HASH
    lock = Lock(amount, 1, locksroot)
    identifier = create_default_identifier(
        alice_app.raiden.address,
        graph.token_address,
        charlie_address,
    )
    mediated_transfer = MediatedTransfer(identifier=identifier,
                                         nonce=1,
                                         token=token_address,
                                         transferred_amount=amount,
                                         recipient=bob_address,
                                         locksroot=locksroot,
                                         lock=lock,
                                         target=charlie_address,
                                         initiator=initiator_address,
                                         fee=0)
    alice_key = PrivateKey(private_keys[0])
    bob_app = mt_helper.get_app_from_address(bob_address)
    sign_and_send(mediated_transfer, alice_key, alice_address, bob_app)
def test_ping_unreachable(raiden_network):
    app0, app1 = raiden_network  # pylint: disable=unbalanced-tuple-unpacking

    # drop everything to force disabling of re-sends
    app0.raiden.protocol.transport.droprate = 1
    app1.raiden.protocol.transport.droprate = 1

    app0.raiden.protocol.retry_interval = 0.1  # for fast tests

    messages = setup_messages_cb()

    ping_message = Ping(nonce=0)
    app0.raiden.sign(ping_message)
    ping_encoded = ping_message.encode()

    async_result = app0.raiden.protocol.send_raw_with_result(
        ping_encoded,
        app1.raiden.address,
    )

    assert async_result.wait(2) is None, "The message was dropped, it can't be acknowledged"

    # Raiden node will start pinging as soon as a new channel
    #  is established. We need to test if
    #  a) there is our original message in the queue
    #  b) there are only Ping message types in
    messages_decoded = [decode(m) for m in messages]
    assert ping_message in messages_decoded
    for message in messages_decoded:
        assert isinstance(message, Ping)
def test_ping(raiden_network):
    app0, app1 = raiden_network  # pylint: disable=unbalanced-tuple-unpacking

    messages = setup_messages_cb()

    ping_message = Ping(nonce=0)
    app0.raiden.sign(ping_message)
    ping_encoded = ping_message.encode()

    async_result = app0.raiden.protocol.send_raw_with_result(
        ping_encoded,
        app1.raiden.address,
    )
    assert async_result.wait(2), 'The message was not acknowledged'

    expected_echohash = sha3(ping_encoded + app1.raiden.address)

    messages_decoded = [decode(m) for m in messages]
    ack_message = next(
        decoded
        for decoded in messages_decoded
        if isinstance(decoded, Ack) and decoded.echo == expected_echohash
    )

    # the ping message was sent and acknowledged
    assert ping_encoded in messages
    assert ack_message
Пример #22
0
def test_mediated_transfer(raiden_network):
    alice_app = raiden_network[0]
    setup_messages_cb()

    graph = alice_app.raiden.channelgraphs.values()[0]
    token_address = graph.token_address
    mt_helper = MediatedTransferTestHelper(raiden_network, graph)

    initiator_address = alice_app.raiden.address
    path = mt_helper.get_paths_of_length(initiator_address, 2)
    mt_helper.assert_path_in_shortest_paths(path, initiator_address, 2)
    alice_address, bob_address, charlie_address = path

    # channels (alice <-> bob <-> charlie)
    channel_ab = mt_helper.get_channel(alice_address, bob_address)
    channel_ba = mt_helper.get_channel(bob_address, alice_address)
    channel_bc = mt_helper.get_channel(bob_address, charlie_address)
    channel_cb = mt_helper.get_channel(charlie_address, bob_address)

    initial_balance_ab = channel_ab.balance
    initial_balance_ba = channel_ba.balance
    initial_balance_bc = channel_bc.balance
    initial_balance_cb = channel_cb.balance

    amount = 10

    result = alice_app.raiden.api.transfer_async(
        token_address,
        amount,
        charlie_address,
    )

    assert channel_ab.locked == amount

    # Cannot assert the intermediary state of the channels since the code is
    # concurrently executed.
    # assert channel_ba.outstanding == amount
    # assert channel_bc.locked == amount
    # assert channel_cb.outstanding == amount

    result.wait()
    assert initial_balance_ab - amount == channel_ab.balance

    gevent.sleep(.1)  # wait for the other nodes to sync
    assert initial_balance_ba + amount == channel_ba.balance
    assert initial_balance_bc - amount == channel_bc.balance
    assert initial_balance_cb + amount == channel_cb.balance
Пример #23
0
def test_webui():
    app_list = create_network(num_nodes=10, num_assets=3, channels_per_node=2)
    app0 = app_list[0]
    addresses = [app.raiden.address.encode('hex') for app in app_list if app != app_list[0]]
    print '\nCreated nodes: \n',
    for node in addresses:
        print node
    setup_messages_cb()
    
    am0 = app0.raiden.assetmanagers.values()[0]
    
    # search for a path of length=2 A > B > C
    num_hops = 2
    source = app0.raiden.address
    
    path_list = am0.channelgraph.get_paths_of_length(source, num_hops)
    assert len(path_list)
    
    for path in path_list:
        assert len(path) == num_hops + 1
        assert path[0] == source
    
    path = path_list[0]
    target = path[-1]
    assert path in am0.channelgraph.get_shortest_paths(source, target)
    assert min(len(p) for p in am0.channelgraph.get_shortest_paths(source, target)) == num_hops + 1
    
    ams_by_address = dict(
        (app.raiden.address, app.raiden.assetmanagers)
        for app in app_list
    )
    
    # addresses
    hop1, hop2, hop3 = path
    
    # asset
    asset_address = am0.asset_address
    
    app0_assets = getattr(app0.raiden.api, 'assets')
    print '\nAvailable assets:'
    for asset in app0_assets:
        print asset.encode('hex')
    print '\n'
    
    handler = UIHandler(app0.raiden)
    ui = WebUI(handler)
    ui.run()
Пример #24
0
def test_ping_dropped_message(raiden_network):
    app0, app1 = raiden_network  # pylint: disable=unbalanced-tuple-unpacking

    # mock transport with packet loss, every 3rd is lost, starting with first message
    UnreliableTransport.droprate = 3
    RaidenProtocol.try_interval = 0.1  # for fast tests
    RaidenProtocol.repeat_messages = True

    messages = setup_messages_cb()
    UnreliableTransport.network.counter = 0

    ping = Ping(nonce=0)
    app0.raiden.sign(ping)
    app0.raiden.protocol.send_and_wait(app1.raiden.address, ping)
    gevent.sleep(1)

    assert len(messages) == 3  # Ping(dropped), Ping, Ack

    for i in [0, 1]:
        assert decode(messages[i]) == ping

    for i in [2]:
        decoded = decode(messages[i])
        assert isinstance(decoded, Ack)

    assert decoded.echo == sha3(ping.encode() + app1.raiden.address)

    messages = setup_messages_cb()
    assert not messages

    UnreliableTransport.network.counter = 2  # first message sent, 2nd dropped
    ping = Ping(nonce=1)
    app0.raiden.sign(ping)
    app0.raiden.protocol.send_and_wait(app1.raiden.address, ping)
    gevent.sleep(1)

    assert len(messages) == 4  # Ping, Ack(dropped), Ping, Ack
    for i in [0, 2]:
        assert decode(messages[i]) == ping
    for i in [1, 3]:
        decoded = decode(messages[i])
        assert isinstance(decoded, Ack)
    assert decoded.echo == sha3(ping.encode() + app1.raiden.address)

    RaidenProtocol.repeat_messages = False
Пример #25
0
def test_healthcheck_with_bad_peer(raiden_network):
    app0, app1 = raiden_network  # pylint: disable=unbalanced-tuple-unpacking
    UnreliableTransport.droprate = 10  # Let's allow some messages to go through
    UnreliableTransport.network.counter = 1
    messages = setup_messages_cb()

    send_ping_time = app0.raiden.config['send_ping_time']
    max_unresponsive_time = app0.raiden.config['max_unresponsive_time']

    graph0 = app0.raiden.channelgraphs.values()[0]
    graph1 = app1.raiden.channelgraphs.values()[0]

    assert graph0.token_address == graph1.token_address
    assert app1.raiden.address in graph0.partneraddress_channel

    amount = 10
    target = app1.raiden.address
    result = app0.raiden.transfer_async(
        graph0.token_address,
        amount,
        target,
    )

    assert result.wait(timeout=10)
    gevent.sleep(2)

    assert graph0.has_path(
        app0.raiden.address,
        app1.raiden.address
    )

    # At this point we should have sent a direct transfer and got back the ack
    assert len(messages) == 2  # DirectTransfer, Ack
    assert isinstance(decode(messages[0]), DirectTransfer)
    assert isinstance(decode(messages[1]), Ack)

    # now let's make things interesting and drop every message
    UnreliableTransport.droprate = 1
    UnreliableTransport.network.counter = 0
    gevent.sleep(send_ping_time)

    # At least 1 ping should have been sent by now but gotten no response
    assert len(messages) >= 3
    for msg in messages[2:]:
        assert isinstance(decode(msg), Ping)

    gevent.sleep(max_unresponsive_time - send_ping_time)
    # By now our peer has not replied and must have been removed from the graph
    assert not graph0.has_path(
        app0.raiden.address,
        app1.raiden.address
    )
    final_messages_num = len(messages)
    # Let's make sure no new pings are sent afterwards
    gevent.sleep(2)
    assert len(messages) == final_messages_num
Пример #26
0
def test_receive_mediatedtransfer_invalid_address(raiden_network, private_keys):
    alice_app = raiden_network[0]
    setup_messages_cb()

    asset_manager = alice_app.raiden.managers_by_asset_address.values()[0]
    asset_address = asset_manager.asset_address

    mt_helper = MediatedTransferTestHelper(raiden_network, asset_manager)
    initiator_address = alice_app.raiden.address
    path = mt_helper.get_paths_of_length(initiator_address, 2)

    alice_address, bob_address, charlie_address = path
    amount = 10
    alice_app.raiden.api.transfer(
        asset_address,
        amount,
        charlie_address,
    )
    gevent.sleep(1.)

    # and now send one more mediated transfer with the same nonce, simulating
    # an out-of-order/resent message that arrives late
    locksroot = HASH
    lock = Lock(amount, 1, locksroot)
    mediated_transfer = MediatedTransfer(
        identifier=asset_manager.transfermanager.create_default_identifier(charlie_address),
        nonce=1,
        asset=asset_address,
        transferred_amount=amount,
        recipient=bob_address,
        locksroot=locksroot,
        lock=lock,
        target=charlie_address,
        initiator=initiator_address,
        fee=0
    )
    alice_key = PrivateKey(private_keys[0])
    target_app = None
    for app in raiden_network:
        if app.raiden.address not in path:
            target_app = app
            break
    sign_and_send(mediated_transfer, alice_key, alice_address, target_app)
Пример #27
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)
Пример #28
0
def test_healthcheck_with_bad_peer(raiden_network):
    app0, app1 = raiden_network  # pylint: disable=unbalanced-tuple-unpacking
    UnreliableTransport.droprate = 10  # Let's allow some messages to go through
    UnreliableTransport.network.counter = 1
    messages = setup_messages_cb()

    send_ping_time = app0.raiden.config['send_ping_time']
    max_unresponsive_time = app0.raiden.config['max_unresponsive_time']

    asset_manager0 = app0.raiden.managers_by_asset_address.values()[0]
    asset_manager1 = app1.raiden.managers_by_asset_address.values()[0]

    assert asset_manager0.asset_address == asset_manager1.asset_address
    assert app1.raiden.address in asset_manager0.partneraddress_channel

    amount = 10
    app0.raiden.api.transfer(
        asset_manager0.asset_address,
        amount,
        target=app1.raiden.address,
    )

    gevent.sleep(2)
    assert asset_manager0.channelgraph.has_path(
        app0.raiden.address,
        app1.raiden.address
    )

    # At this point we should have sent a direct transfer and got back the ack
    assert len(messages) == 2  # DirectTransfer, Ack
    assert isinstance(decode(messages[0]), DirectTransfer)
    assert isinstance(decode(messages[1]), Ack)

    # now let's make things interesting and drop every message
    UnreliableTransport.droprate = 1
    UnreliableTransport.network.counter = 0
    gevent.sleep(send_ping_time)

    # At least 1 ping should have been sent by now but gotten no response
    assert len(messages) >= 3
    for msg in messages[2:]:
        assert isinstance(decode(msg), Ping)

    gevent.sleep(max_unresponsive_time - send_ping_time)
    # By now our peer has not replied and must have been removed from the graph
    assert not asset_manager0.channelgraph.has_path(
        app0.raiden.address,
        app1.raiden.address
    )
    final_messages_num = len(messages)
    # Let's make sure no new pings are sent afterwards
    gevent.sleep(2)
    assert len(messages) == final_messages_num
Пример #29
0
def test_ping_udp(raiden_network):
    app0, app1 = raiden_network  # pylint: disable=unbalanced-tuple-unpacking
    messages = setup_messages_cb()
    ping = Ping(nonce=0)
    app0.raiden.sign(ping)
    app0.raiden.protocol.send_and_wait(app1.raiden.address, ping)
    gevent.sleep(0.1)
    assert len(messages) == 2  # Ping, Ack
    assert decode(messages[0]) == ping
    decoded = decode(messages[1])
    assert isinstance(decoded, Ack)
    assert decoded.echo == sha3(ping.encode() + app1.raiden.address)
Пример #30
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)
Пример #31
0
def test_ping():
    apps = create_network(num_nodes=2, num_assets=0, channels_per_node=0)
    app0, app1 = apps  # pylint: disable=unbalanced-tuple-unpacking
    messages = setup_messages_cb()
    ping = Ping(nonce=0)
    app0.raiden.sign(ping)
    app0.raiden.protocol.send(app1.raiden.address, ping)
    gevent.sleep(0.1)
    assert len(messages) == 2  # Ping, Ack
    assert decode(messages[0]) == ping
    decoded = decode(messages[1])
    assert isinstance(decoded, Ack)
    assert decoded.echo == ping.hash
Пример #32
0
def test_mediated_transfer(raiden_network):
    alice_app = raiden_network[0]
    setup_messages_cb()

    asset_manager = alice_app.raiden.managers_by_asset_address.values()[0]
    asset_address = asset_manager.asset_address
    mt_helper = MediatedTransferTestHelper(raiden_network, asset_manager)

    initiator_address = alice_app.raiden.address
    path = mt_helper.get_paths_of_length(initiator_address, 2)
    mt_helper.assert_path_in_shortest_paths(path, initiator_address, 2)
    alice_address, bob_address, charlie_address = path

    # channels (alice <-> bob <-> charlie)
    channel_ab = mt_helper.get_channel(alice_address, bob_address)
    channel_ba = mt_helper.get_channel(bob_address, alice_address)
    channel_bc = mt_helper.get_channel(bob_address, charlie_address)
    channel_cb = mt_helper.get_channel(charlie_address, bob_address)

    initial_balance_ab = channel_ab.balance
    initial_balance_ba = channel_ba.balance
    initial_balance_bc = channel_bc.balance
    initial_balance_cb = channel_cb.balance

    amount = 10

    alice_app.raiden.api.transfer(
        asset_address,
        amount,
        charlie_address,
    )

    gevent.sleep(1.)

    assert initial_balance_ab - amount == channel_ab.balance
    assert initial_balance_ba + amount == channel_ba.balance
    assert initial_balance_bc - amount == channel_bc.balance
    assert initial_balance_cb + amount == channel_cb.balance
Пример #33
0
def test_receive_mediatedtransfer_outoforder(raiden_network, private_keys):
    alice_app = raiden_network[0]
    bob_app = raiden_network[1]

    messages = setup_messages_cb()

    graph = alice_app.raiden.token_to_channelgraph.values()[0]
    token_address = graph.token_address

    channel0 = channel(alice_app, bob_app, token_address)

    mt_helper = MediatedTransferTestHelper(raiden_network, graph)
    initiator_address = alice_app.raiden.address
    path = mt_helper.get_paths_of_length(initiator_address, 2)

    # make sure we have no messages before the transfer
    assert not messages

    alice_address, bob_address, charlie_address = path
    amount = 10
    result = alice_app.raiden.transfer_async(
        token_address,
        amount,
        charlie_address,
    )

    assert result.wait(timeout=10)
    gevent.sleep(1.)

    # and now send one more mediated transfer with the same nonce, simulating
    # an out-of-order/resent message that arrives late
    lock = Lock(amount, 1, UNIT_HASHLOCK)
    identifier = create_default_identifier()
    mediated_transfer = MediatedTransfer(identifier=identifier,
                                         nonce=1,
                                         token=token_address,
                                         channel=channel0.channel_address,
                                         transferred_amount=amount,
                                         recipient=bob_address,
                                         locksroot=UNIT_HASHLOCK,
                                         lock=lock,
                                         target=charlie_address,
                                         initiator=initiator_address,
                                         fee=0)
    alice_key = PrivateKey(private_keys[0])
    bob_app = mt_helper.get_app_from_address(bob_address)
    sign_and_send(mediated_transfer, alice_key, alice_address, bob_app)
def test_direct_transfer(raiden_network):
    app0, app1 = raiden_network  # pylint: disable=unbalanced-tuple-unpacking

    messages = setup_messages_cb()

    graph0 = app0.raiden.token_to_channelgraph.values()[0]
    graph1 = app1.raiden.token_to_channelgraph.values()[0]

    channel0 = graph0.partneraddress_to_channel[app1.raiden.address]
    channel1 = graph1.partneraddress_to_channel[app0.raiden.address]

    balance0 = channel0.balance
    balance1 = channel1.balance

    assert graph0.token_address == graph1.token_address
    assert app1.raiden.address in graph0.partneraddress_to_channel

    amount = 10
    target = app1.raiden.address
    result = app0.raiden.direct_transfer_async(
        graph0.token_address,
        amount,
        target,
        identifier=1,
    )

    result.wait(timeout=10)
    gevent.sleep(5)

    assert_synched_channels(
        channel0, balance0 - amount, [],
        channel1, balance1 + amount, []
    )

    decoded_messages = [decode(m) for m in messages]
    direct_messages = get_messages_by_type(decoded_messages, DirectTransfer)

    assert len(direct_messages) == 1
    assert direct_messages[0].transferred_amount == amount

    assert_ack_for(
        app1,
        direct_messages[0],
        decoded_messages,
    )
def test_direct_transfer(raiden_network):
    app0, app1 = raiden_network  # pylint: disable=unbalanced-tuple-unpacking

    messages = setup_messages_cb()

    graph0 = list(app0.raiden.token_to_channelgraph.values())[0]
    graph1 = list(app1.raiden.token_to_channelgraph.values())[0]

    channel0 = graph0.partneraddress_to_channel[app1.raiden.address]
    channel1 = graph1.partneraddress_to_channel[app0.raiden.address]

    balance0 = channel0.balance
    balance1 = channel1.balance

    assert graph0.token_address == graph1.token_address
    assert app1.raiden.address in graph0.partneraddress_to_channel

    amount = 10
    target = app1.raiden.address
    result = app0.raiden.direct_transfer_async(
        graph0.token_address,
        amount,
        target,
        identifier=1,
    )

    assert result.wait(timeout=10)
    gevent.sleep(5)

    assert_synched_channels(
        channel0, balance0 - amount, [],
        channel1, balance1 + amount, []
    )

    decoded_messages = [decode(m) for m in messages]
    direct_messages = get_messages_by_type(decoded_messages, DirectTransfer)

    assert len(direct_messages) == 1
    assert direct_messages[0].transferred_amount == amount

    assert_ack_for(
        app1,
        direct_messages[0],
        decoded_messages,
    )
Пример #36
0
def test_ping_unreachable(raiden_network):
    app0, app1 = raiden_network  # pylint: disable=unbalanced-tuple-unpacking

    UnreliableTransport.droprate = 1  # drop everything to force disabling of re-sends
    RaidenProtocol.try_interval = 0.1  # for fast tests
    RaidenProtocol.repeat_messages = True

    messages = setup_messages_cb()
    UnreliableTransport.network.counter = 0

    ping = Ping(nonce=0)
    app0.raiden.sign(ping)
    app0.raiden.protocol.send_and_wait(app1.raiden.address, ping)
    gevent.sleep(2)

    assert len(messages) == 5  # 5 dropped Pings
    for i, message in enumerate(messages):
        assert decode(message) == ping

    RaidenProtocol.repeat_messages = False
Пример #37
0
def test_ping_unreachable(raiden_network):
    app0, app1 = raiden_network  # pylint: disable=unbalanced-tuple-unpacking

    UnreliableTransport.droprate = 1  # drop everything to force disabling of re-sends
    app0.raiden.protocol.retry_interval = 0.1  # for fast tests

    messages = setup_messages_cb()
    UnreliableTransport.network.counter = 0

    ping = Ping(nonce=0)
    app0.raiden.sign(ping)
    async_result = app0.raiden.protocol.send_async(
        app1.raiden.address,
        ping,
    )

    assert async_result.wait(
        2) is None, "the message was dropped, it can't be acknowledged"

    for message in messages:
        assert decode(message) == ping
Пример #38
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)
Пример #39
0
def test_ping_ordering(raiden_network):
    app0, app1 = raiden_network  # pylint: disable=unbalanced-tuple-unpacking

    # mock transport with packet loss, every 3rd is lost, starting with first message
    droprate = UnreliableTransport.droprate = 3
    RaidenProtocol.try_interval = 0.1  # for fast tests
    RaidenProtocol.repeat_messages = True

    messages = setup_messages_cb()
    UnreliableTransport.network.counter = 0

    ping_amount = 5

    hashes = []
    for nonce in range(ping_amount):
        ping = Ping(nonce=nonce)
        app0.raiden.sign(ping)
        app0.raiden.protocol.send_and_wait(app1.raiden.address, ping)
        pinghash = sha3(ping.encode() + app1.raiden.address)
        hashes.append(pinghash)

    gevent.sleep(2)  # give some time for messages to be handled

    expected_message_amount = ping_amount * droprate
    assert len(messages) == expected_message_amount

    for i in range(0, expected_message_amount, droprate):
        assert isinstance(decode(messages[i]), Ping)

    for i in range(1, expected_message_amount, droprate):
        assert isinstance(decode(messages[i]), Ping)

    for i, j in zip(range(2, expected_message_amount, droprate), range(ping_amount)):
        decoded = decode(messages[i])
        assert isinstance(decoded, Ack)
        assert decoded.echo == hashes[j]

    RaidenProtocol.repeat_messages = False
Пример #40
0
def test_transfer(raiden_network):
    app0, app1 = raiden_network  # pylint: disable=unbalanced-tuple-unpacking

    messages = setup_messages_cb()
    mlogger = MessageLogger()

    a0_address = pex(app0.raiden.address)
    a1_address = pex(app1.raiden.address)

    asset_manager0 = app0.raiden.managers_by_asset_address.values()[0]
    asset_manager1 = app1.raiden.managers_by_asset_address.values()[0]

    channel0 = asset_manager0.partneraddress_channel[app1.raiden.address]
    channel1 = asset_manager1.partneraddress_channel[app0.raiden.address]

    balance0 = channel0.balance
    balance1 = channel1.balance

    assert asset_manager0.asset_address == asset_manager1.asset_address
    assert app1.raiden.address in asset_manager0.partneraddress_channel

    amount = 10
    app0.raiden.api.transfer(
        asset_manager0.asset_address,
        amount,
        target=app1.raiden.address,
    )
    gevent.sleep(1)

    assert_synched_channels(
        channel0, balance0 - amount, [],
        channel1, balance1 + amount, []
    )

    assert len(messages) == 2  # DirectTransfer, Ack
    directtransfer_message = decode(messages[0])
    assert isinstance(directtransfer_message, DirectTransfer)
    assert directtransfer_message.transferred_amount == amount

    ack_message = decode(messages[1])
    assert isinstance(ack_message, Ack)
    assert ack_message.echo == sha3(directtransfer_message.encode() + app1.raiden.address)

    a0_messages = mlogger.get_node_messages(a0_address)
    assert len(a0_messages) == 2
    assert isinstance(a0_messages[0], DirectTransfer)
    assert isinstance(a0_messages[1], Ack)

    a0_sent_messages = mlogger.get_node_messages(a0_address, only='sent')
    assert len(a0_sent_messages) == 1
    assert isinstance(a0_sent_messages[0], DirectTransfer)

    a0_recv_messages = mlogger.get_node_messages(a0_address, only='recv')
    assert len(a0_recv_messages) == 1
    assert isinstance(a0_recv_messages[0], Ack)

    a1_messages = mlogger.get_node_messages(a1_address)
    assert len(a1_messages) == 2
    assert isinstance(a1_messages[0], Ack)
    assert isinstance(a1_messages[1], DirectTransfer)

    a1_sent_messages = mlogger.get_node_messages(a1_address, only='sent')
    assert len(a1_sent_messages) == 1
    assert isinstance(a1_sent_messages[0], Ack)

    a1_recv_messages = mlogger.get_node_messages(a1_address, only='recv')
    assert len(a1_recv_messages) == 1
    assert isinstance(a1_recv_messages[0], DirectTransfer)
Пример #41
0
def test_transfer():
    apps = create_network(num_nodes=2, num_assets=1, channels_per_node=1)
    app0, app1 = apps  # pylint: disable=unbalanced-tuple-unpacking

    messages = setup_messages_cb()
    mlogger = MessageLogger()

    a0_address = pex(app0.raiden.address)
    a1_address = pex(app1.raiden.address)

    asset_manager0 = app0.raiden.assetmanagers.values()[0]
    asset_manager1 = app1.raiden.assetmanagers.values()[0]

    channel0 = asset_manager0.channels[app1.raiden.address]
    channel1 = asset_manager1.channels[app0.raiden.address]

    balance0 = channel0.our_state.balance
    balance1 = channel1.our_state.balance

    assert asset_manager0.asset_address == asset_manager1.asset_address
    assert app1.raiden.address in asset_manager0.channels

    amount = 10
    app0.raiden.api.transfer(
        asset_manager0.asset_address,
        amount,
        target=app1.raiden.address,
    )
    gevent.sleep(1)

    assert_synched_channels(
        channel0, balance0 - amount, [],
        channel1, balance1 + amount, []
    )

    assert len(messages) == 2  # DirectTransfer, Ack
    directtransfer_message = decode(messages[0])
    assert isinstance(directtransfer_message, DirectTransfer)
    assert directtransfer_message.balance == balance1 + amount

    ack_message = decode(messages[1])
    assert isinstance(ack_message, Ack)
    assert ack_message.echo == directtransfer_message.hash

    a0_messages = mlogger.get_node_messages(a0_address)
    assert len(a0_messages) == 2
    assert isinstance(a0_messages[0], DirectTransfer)
    assert isinstance(a0_messages[1], Ack)

    a0_sent_messages = mlogger.get_node_messages(a0_address, only='sent')
    assert len(a0_sent_messages) == 1
    assert isinstance(a0_sent_messages[0], DirectTransfer)

    a0_recv_messages = mlogger.get_node_messages(a0_address, only='recv')
    assert len(a0_recv_messages) == 1
    assert isinstance(a0_recv_messages[0], Ack)

    a1_messages = mlogger.get_node_messages(a1_address)
    assert len(a1_messages) == 2
    assert isinstance(a1_messages[0], Ack)
    assert isinstance(a1_messages[1], DirectTransfer)

    a1_sent_messages = mlogger.get_node_messages(a1_address, only='sent')
    assert len(a1_sent_messages) == 1
    assert isinstance(a1_sent_messages[0], Ack)

    a1_recv_messages = mlogger.get_node_messages(a1_address, only='recv')
    assert len(a1_recv_messages) == 1
    assert isinstance(a1_recv_messages[0], DirectTransfer)
Пример #42
0
def test_webui():  # pylint: disable=too-many-locals
    num_assets = 3
    num_nodes = 10
    verbose = 0
    settle_timeout = DEFAULT_SETTLE_TIMEOUT

    assets_addresses = [
        sha3('webui:asset:{}'.format(number))[:20]
        for number in range(num_assets)
    ]

    private_keys = [
        sha3('webui:{}'.format(position))
        for position in range(num_nodes)
    ]

    BlockChainServiceMock.reset()
    blockchain_service = BlockChainServiceMock(None, MOCK_REGISTRY_ADDRESS)
    registry = blockchain_service.registry(MOCK_REGISTRY_ADDRESS)

    for asset in assets_addresses:
        registry.add_asset(asset)

    channels_per_node = 2
    deposit = 100

    blockchain_services = [
        BlockChainServiceMock(privkey, MOCK_REGISTRY_ADDRESS)
        for privkey in private_keys
    ]

    app_list = create_apps(
        blockchain_services,
        UDPTransport,
        verbose,
    )

    create_network_channels(
        app_list,
        assets_addresses,
        channels_per_node,
        deposit,
        settle_timeout,
    )

    app0 = app_list[0]

    addresses = [
        app.raiden.address.encode('hex')
        for app in app_list
        if app != app_list[0]
    ]

    print '\nCreated nodes: \n',
    for node in addresses:
        print node

    setup_messages_cb()

    app0_assets = getattr(app0.raiden.api, 'assets')
    print '\nAvailable assets:'
    for asset in app0_assets:
        print asset.encode('hex')
    print '\n'

    wamp = WAMPRouter(app0.raiden, 8080, ['channel', 'test'])
    wamp.run()

    BlockChainServiceMock.reset()
Пример #43
0
def test_settlement():
    apps = create_network(num_nodes=2, num_assets=1, channels_per_node=1)
    app0, app1 = apps  # pylint: disable=unbalanced-tuple-unpacking

    setup_messages_cb()

    asset_manager0 = app0.raiden.assetmanagers.values()[0]
    asset_manager1 = app1.raiden.assetmanagers.values()[0]

    chain0 = app0.raiden.chain
    asset_address = asset_manager0.asset_address

    channel0 = asset_manager0.channels[app1.raiden.address]
    channel1 = asset_manager1.channels[app0.raiden.address]

    balance0 = channel0.balance
    balance1 = channel1.balance

    amount = 10
    expiration = 10
    secret = 'secret'
    hashlock = sha3(secret)

    assert app1.raiden.address in asset_manager0.channels
    assert asset_manager0.asset_address == asset_manager1.asset_address
    assert channel0.nettingcontract_address == channel1.nettingcontract_address

    transfermessage = channel0.create_lockedtransfer(amount, expiration, hashlock)
    app0.raiden.sign(transfermessage)
    channel0.register_transfer(transfermessage)
    channel1.register_transfer(transfermessage)

    assert_synched_channels(
        channel0, balance0, [transfermessage.lock],
        channel1, balance1, []
    )

    # Bob learns the secret, but Alice did not send a signed updated balance to
    # reflect this Bob wants to settle

    nettingcontract_address = channel0.nettingcontract_address
    last_sent_transfers = [transfermessage]

    # get proof, that locked transfermessage was in merkle tree, with locked.root
    merkle_proof = channel1.our_state.locked.get_proof(transfermessage)
    root = channel1.our_state.locked.root
    assert check_proof(merkle_proof, root, sha3(transfermessage.lock.as_bytes))

    unlocked = [(merkle_proof, transfermessage.lock, secret)]

    chain0.close(
        asset_address,
        nettingcontract_address,
        app0.raiden.address,
        last_sent_transfers,
        unlocked,
    )

    for _ in range(NettingChannelContract.locked_time):
        chain0.next_block()

    chain0.settle(asset_address, nettingcontract_address)
Пример #44
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)
Пример #45
0
def test_mediated_transfer(raiden_network):

    def get_channel(from_, to_):
        return ams_by_address[from_][asset_address].partneraddress_channel[to_]

    alice_app = raiden_network[0]
    setup_messages_cb()

    asset_manager = alice_app.raiden.managers_by_asset_address.values()[0]
    asset_address = asset_manager.asset_address

    # search for a path of length=2 A > B > C
    num_hops = 2
    initiator_address = alice_app.raiden.address

    paths_length_2 = asset_manager.channelgraph.get_paths_of_length(
        initiator_address,
        num_hops,
    )

    assert len(paths_length_2)
    for path in paths_length_2:
        assert len(path) == num_hops + 1
        assert path[0] == initiator_address

    path = paths_length_2[0]

    alice_address, bob_address, charlie_address = path

    shortest_paths = list(asset_manager.channelgraph.get_shortest_paths(
        initiator_address,
        charlie_address,
    ))

    assert path in shortest_paths
    assert min(len(path) for path in shortest_paths) == num_hops + 1

    ams_by_address = dict(
        (app.raiden.address, app.raiden.managers_by_asset_address)
        for app in raiden_network
    )

    # channels (alice <-> bob <-> charlie)
    channel_ab = get_channel(alice_address, bob_address)
    channel_ba = get_channel(bob_address, alice_address)
    channel_bc = get_channel(bob_address, charlie_address)
    channel_cb = get_channel(charlie_address, bob_address)

    initial_balance_ab = channel_ab.balance
    initial_balance_ba = channel_ba.balance
    initial_balance_bc = channel_bc.balance
    initial_balance_cb = channel_cb.balance

    amount = 10

    alice_app.raiden.api.transfer(
        asset_address,
        amount,
        charlie_address,
    )

    gevent.sleep(1.)

    assert initial_balance_ab - amount == channel_ab.balance
    assert initial_balance_ba + amount == channel_ba.balance
    assert initial_balance_bc - amount == channel_bc.balance
    assert initial_balance_cb + amount == channel_cb.balance
Пример #46
0
def test_settlement(raiden_network, settle_timeout, reveal_timeout):
    app0, app1 = raiden_network  # pylint: disable=unbalanced-tuple-unpacking

    setup_messages_cb()

    asset_manager0 = app0.raiden.managers_by_asset_address.values()[0]
    asset_manager1 = app1.raiden.managers_by_asset_address.values()[0]

    chain0 = app0.raiden.chain

    channel0 = asset_manager0.partneraddress_channel[app1.raiden.address]
    channel1 = asset_manager1.partneraddress_channel[app0.raiden.address]

    balance0 = channel0.balance
    balance1 = channel1.balance

    amount = 10
    expiration = app0.raiden.chain.block_number() + reveal_timeout + 1
    secret = 'secret'
    hashlock = sha3(secret)

    assert app1.raiden.address in asset_manager0.partneraddress_channel
    assert asset_manager0.asset_address == asset_manager1.asset_address

    nettingaddress0 = channel0.external_state.netting_channel.address
    nettingaddress1 = channel1.external_state.netting_channel.address
    assert nettingaddress0 == nettingaddress1

    identifier = 1
    fee = 0
    transfermessage = channel0.create_mediatedtransfer(
        app0.raiden.address,
        app1.raiden.address,
        fee,
        amount,
        identifier,
        expiration,
        hashlock,
    )
    app0.raiden.sign(transfermessage)
    channel0.register_transfer(transfermessage)
    channel1.register_transfer(transfermessage)

    assert_synched_channels(
        channel0, balance0, [],
        channel1, balance1, [transfermessage.lock],
    )

    # At this point we are assuming the following:
    #
    #    A -> B MediatedTransfer
    #    B -> A SecretRequest
    #    A -> B RevealSecret
    #    - protocol didn't continue
    #
    # B knowns the secret but doesn't have an updated balance proof, B needs to
    # call settle.

    # get proof, that locked transfermessage was in merkle tree, with locked.root
    lock = channel1.our_state.balance_proof.get_lock_by_hashlock(hashlock)
    unlock_proof = channel1.our_state.balance_proof.compute_proof_for_lock(secret, lock)

    root = channel1.our_state.balance_proof.merkleroot_for_unclaimed()

    assert check_proof(
        unlock_proof.merkle_proof,
        root,
        sha3(transfermessage.lock.as_bytes),
    )
    assert unlock_proof.lock_encoded == transfermessage.lock.as_bytes
    assert unlock_proof.secret == secret

    # a ChannelClose event will be generated, this will be polled by both apps
    # and each must start a task for calling settle
    channel0.external_state.netting_channel.close(
        app0.raiden.address,
        transfermessage,
        None,
    )

    # unlock will not be called by Channel.channel_closed because we did not
    # register the secret
    channel0.external_state.netting_channel.unlock(
        app0.raiden.address,
        [unlock_proof],
    )

    settle_expiration = chain0.block_number() + settle_timeout
    wait_until_block(chain0, settle_expiration)

    # settle must be called by the apps triggered by the ChannelClose event,
    # and the channels must update it's state based on the ChannelSettled event
    assert channel0.external_state.settled_block != 0
    assert channel1.external_state.settled_block != 0
def test_settlement(raiden_network, settle_timeout, reveal_timeout):
    alice_app, bob_app = raiden_network  # pylint: disable=unbalanced-tuple-unpacking

    setup_messages_cb()

    alice_graph = list(alice_app.raiden.token_to_channelgraph.values())[0]
    bob_graph = list(bob_app.raiden.token_to_channelgraph.values())[0]
    assert alice_graph.token_address == bob_graph.token_address

    alice_bob_channel = alice_graph.partneraddress_to_channel[bob_app.raiden.address]
    bob_alice_channel = bob_graph.partneraddress_to_channel[alice_app.raiden.address]

    alice_deposit = alice_bob_channel.balance
    bob_deposit = bob_alice_channel.balance

    token = alice_app.raiden.chain.token(alice_bob_channel.token_address)

    alice_balance = token.balance_of(alice_app.raiden.address)
    bob_balance = token.balance_of(bob_app.raiden.address)

    alice_chain = alice_app.raiden.chain

    alice_to_bob_amount = 10
    expiration = alice_app.raiden.chain.block_number() + reveal_timeout + 1
    secret = b'secretsecretsecretsecretsecretse'
    hashlock = sha3(secret)

    assert bob_app.raiden.address in alice_graph.partneraddress_to_channel

    nettingaddress0 = alice_bob_channel.external_state.netting_channel.address
    nettingaddress1 = bob_alice_channel.external_state.netting_channel.address
    assert nettingaddress0 == nettingaddress1

    identifier = 1
    fee = 0
    transfermessage = alice_bob_channel.create_mediatedtransfer(
        alice_app.raiden.address,
        bob_app.raiden.address,
        fee,
        alice_to_bob_amount,
        identifier,
        expiration,
        hashlock,
    )
    alice_app.raiden.sign(transfermessage)
    alice_bob_channel.register_transfer(
        alice_app.raiden.get_block_number(),
        transfermessage,
    )
    bob_alice_channel.register_transfer(
        bob_app.raiden.get_block_number(),
        transfermessage,
    )

    assert_synched_channels(
        alice_bob_channel, alice_deposit, [],
        bob_alice_channel, bob_deposit, [transfermessage.lock],
    )

    # At this point we are assuming the following:
    #
    #    A -> B MediatedTransfer
    #    B -> A SecretRequest
    #    A -> B RevealSecret
    #    - protocol didn't continue
    #
    # B knowns the secret but doesn't have an updated balance proof, B needs to
    # call settle.

    # get proof, that locked transfermessage was in merkle tree, with locked.root
    lock = bob_alice_channel.partner_state.get_lock_by_hashlock(hashlock)
    assert sha3(secret) == hashlock
    unlock_proof = bob_alice_channel.partner_state.compute_proof_for_lock(secret, lock)

    root = merkleroot(bob_alice_channel.partner_state.merkletree)

    assert validate_proof(
        unlock_proof.merkle_proof,
        root,
        sha3(transfermessage.lock.as_bytes),
    )
    assert unlock_proof.lock_encoded == transfermessage.lock.as_bytes
    assert unlock_proof.secret == secret

    # a ChannelClose event will be generated, this will be polled by both apps
    # and each must start a task for calling settle
    balance_proof = transfermessage.to_balanceproof()
    bob_alice_channel.external_state.close(balance_proof)
    wait_until_block(alice_chain, alice_chain.block_number() + 1)

    assert alice_bob_channel.external_state.close_event.wait(timeout=15)
    assert bob_alice_channel.external_state.close_event.wait(timeout=15)

    assert alice_bob_channel.external_state.closed_block != 0
    assert bob_alice_channel.external_state.closed_block != 0
    assert alice_bob_channel.external_state.settled_block == 0
    assert bob_alice_channel.external_state.settled_block == 0

    # unlock will not be called by Channel.channel_closed because we did not
    # register the secret
    assert lock.expiration > alice_app.raiden.chain.block_number()
    assert lock.hashlock == sha3(secret)

    bob_alice_channel.external_state.netting_channel.withdraw([unlock_proof])

    settle_expiration = alice_chain.block_number() + settle_timeout + 2
    wait_until_block(alice_chain, settle_expiration)

    assert alice_bob_channel.external_state.settle_event.wait(timeout=15)
    assert bob_alice_channel.external_state.settle_event.wait(timeout=15)
    # settle must be called by the apps triggered by the ChannelClose event,
    # and the channels must update it's state based on the ChannelSettled event
    assert alice_bob_channel.external_state.settled_block != 0
    assert bob_alice_channel.external_state.settled_block != 0

    address0 = alice_app.raiden.address
    address1 = bob_app.raiden.address

    alice_netted_balance = alice_balance + alice_deposit - alice_to_bob_amount
    bob_netted_balance = bob_balance + bob_deposit + alice_to_bob_amount

    assert token.balance_of(address0) == alice_netted_balance
    assert token.balance_of(address1) == bob_netted_balance

    # Now let's query the WAL to see if the state changes were logged as expected
    state_changes = [
        change[1] for change in get_all_state_changes(alice_app.raiden.transaction_log)
        if not isinstance(change[1], Block)
    ]

    assert must_contain_entry(state_changes, ContractReceiveClosed, {
        'channel_address': nettingaddress0,
        'closing_address': bob_app.raiden.address,
        'block_number': alice_bob_channel.external_state.closed_block,
    })

    assert must_contain_entry(state_changes, ReceiveSecretReveal, {
        'secret': secret,
        'sender': bob_app.raiden.address,
    })

    assert must_contain_entry(state_changes, ContractReceiveWithdraw, {
        'channel_address': nettingaddress0,
        'secret': secret,
        'receiver': bob_app.raiden.address,
    })

    assert must_contain_entry(state_changes, ContractReceiveSettled, {
        'channel_address': nettingaddress0,
        'block_number': bob_alice_channel.external_state.settled_block,
    })