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()
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()
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()
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
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
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()
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)
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
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
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
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)
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)
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
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
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
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
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()
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
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
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)
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)
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
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)
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)
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
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
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, )
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
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
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)
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
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)
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)
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()
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)
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)
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
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, })