def setup_apps(amount, assets, num_transfers, num_nodes, channels_per_node): assert len(assets) <= num_nodes deposit = amount * num_transfers private_keys = [ sha3('mediated_transfer:{}'.format(position)) for position in range(num_nodes) ] BlockChainServiceMock.reset() blockchain_services = list() for privkey in private_keys: blockchain = BlockChainServiceMock( privkey, MOCK_REGISTRY_ADDRESS, ) blockchain_services.append(blockchain) registry = blockchain_services[0].registry(MOCK_REGISTRY_ADDRESS) for asset in assets: registry.add_asset(asset) verbosity = 3 apps = create_network( blockchain_services, assets, channels_per_node, deposit, DEFAULT_SETTLE_TIMEOUT, UDPTransport, verbosity, ) return apps
def raiden_network(request, private_keys, assets_addresses, channels_per_node, deposit, settle_timeout, poll_timeout, registry_address, blockchain_service, transport_class): blockchain_service_class = BlockChainServiceMock registry = blockchain_service.registry(registry_address) for asset in assets_addresses: registry.add_asset(asset) raiden_apps = create_network( private_keys, assets_addresses, registry_address, channels_per_node, deposit, settle_timeout, poll_timeout, transport_class, blockchain_service_class, ) _raiden_cleanup(request, raiden_apps) return raiden_apps
def transfer_speed(num_transfers=100, max_locked=100): # pylint: disable=too-many-locals channels_per_node = 1 num_nodes = 2 num_tokens = 1 private_keys = [ sha3('speed:{}'.format(position)) for position in range(num_nodes) ] tokens = [ sha3('token:{}'.format(number))[:20] for number in range(num_tokens) ] amounts = [a % 100 + 1 for a in range(1, num_transfers + 1)] deposit = sum(amounts) secrets = [str(i) for i in range(num_transfers)] BlockChainServiceMock._instance = True blockchain_service = BlockChainServiceMock(None, MOCK_REGISTRY_ADDRESS) BlockChainServiceMock._instance = blockchain_service # pylint: disable=redefined-variable-type registry = blockchain_service.registry(MOCK_REGISTRY_ADDRESS) for token in tokens: registry.add_token(token) apps = create_network(private_keys, tokens, MOCK_REGISTRY_ADDRESS, channels_per_node, deposit, DEFAULT_SETTLE_TIMEOUT, DEFAULT_POLL_TIMEOUT, UDPTransport, BlockChainServiceMock) app0, app1 = apps # pylint: disable=unbalanced-tuple-unpacking channel0 = app0.raiden.channelgraphs[tokens[0]].address_channel.values()[0] channel1 = app1.raiden.channelgraphs[tokens[0]].address_channel.values()[0] expiration = app0.raiden.chain.block_number() + DEFAULT_REVEAL_TIMEOUT + 3 start = time.time() for i, amount in enumerate(amounts): hashlock = sha3(secrets[i]) locked_transfer = channel0.create_lockedtransfer( amount=amount, identifier=1, # TODO: fill in identifier expiration=expiration, hashlock=hashlock, ) app0.raiden.sign(locked_transfer) channel0.register_transfer(locked_transfer) channel1.register_transfer(locked_transfer) if i > max_locked: idx = i - max_locked secret = secrets[idx] channel0.register_secret(secret) channel1.register_secret(secret) elapsed = time.time() - start print('%d transfers per second' % (num_transfers / elapsed))
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 transfer_speed(num_transfers=100, max_locked=100): # pylint: disable=too-many-locals channels_per_node = 1 deposit = 100 num_nodes = 2 num_assets = 1 private_keys = [ sha3('speed:{}'.format(position)) for position in range(num_nodes) ] assets = [ sha3('asset:{}'.format(number))[:20] for number in range(num_assets) ] apps = create_network( private_keys, assets, MOCK_REGISTRY_ADDRESS, channels_per_node, deposit, DEFAULT_SETTLE_TIMEOUT, UDPTransport, BlockChainServiceMock ) app0, app1 = apps # pylint: disable=unbalanced-tuple-unpacking channel0 = app0.raiden.assetmanagers.values()[0].channels.values()[0] channel1 = app1.raiden.assetmanagers.values()[0].channels.values()[0] amounts = [a % 100 + 1 for a in range(1, num_transfers + 1)] secrets = [str(i) for i in range(num_transfers)] expiration = app0.raiden.chain.block_number + 100 start = time.time() for i, amount in enumerate(amounts): hashlock = sha3(secrets[i]) locked_transfer = channel0.create_lockedtransfer( amount=amount, expiration=expiration, hashlock=hashlock, ) app0.raiden.sign(locked_transfer) channel0.register_transfer(locked_transfer) channel1.register_transfer(locked_transfer) if i > max_locked: idx = i - max_locked secret = secrets[idx] channel0.claim_locked(secret) channel1.claim_locked(secret) elapsed = time.time() - start print('%d transfers per second' % (num_transfers / elapsed))
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_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_create_network(): apps = create_network(num_nodes=10, num_assets=2, channels_per_node=4) assert len(apps) == 10 # All apps must reference the same chain for app in apps: assert app.raiden.chain == apps[0].raiden.chain # All apps must have 2 asset managers (one per each asset) for app in apps: assert len(set(app.raiden.assetmanagers.keys())) == 2 # All apps must have uniq private keys assert len(set([app.raiden.privkey for app in apps])) == 10
def setup_apps(amount, tokens, num_transfers, num_nodes, channels_per_node): assert len(tokens) <= num_nodes deposit = amount * num_transfers private_keys = [ sha3('mediated_transfer:{}'.format(position)) for position in range(num_nodes) ] blockchain_services = list() tester = tester_state( private_keys[0], private_keys, tester_blockgas_limit(), ) nettingchannel_library_address = tester_nettingchannel_library_address( tester_state, ) channelmanager_library_address = tester_channelmanager_library_address( tester_state, nettingchannel_library_address, ) registry_address = tester_registry_address( tester_state, channelmanager_library_address, ) for privkey in private_keys: blockchain = BlockChainServiceTesterMock( privkey, tester, registry_address, ) blockchain_services.append(blockchain) registry = blockchain_services[0].registry(registry_address) for token in tokens: registry.add_token(token) verbosity = 3 apps = create_network( blockchain_services, tokens, channels_per_node, deposit, DEFAULT_SETTLE_TIMEOUT, UDPTransport, verbosity, ) return apps
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_locked_transfer(): """ Simple locked transfer test. """ apps = create_network(num_nodes=2, num_assets=1, channels_per_node=1) app0, app1 = apps # pylint: disable=unbalanced-tuple-unpacking channel0 = app0.raiden.assetmanagers.values()[0].channels.values()[0] channel1 = app1.raiden.assetmanagers.values()[0].channels.values()[0] balance0 = channel0.balance balance1 = channel1.balance amount = 10 expiration = app0.raiden.chain.block_number + 15 # reveal_timeout <= expiration < contract.lock_time secret = 'secret' hashlock = sha3(secret) locked_transfer = channel0.create_lockedtransfer( amount=amount, expiration=expiration, hashlock=hashlock, ) app0.raiden.sign(locked_transfer) channel0.register_transfer(locked_transfer) channel1.register_transfer(locked_transfer) # don't update balances but update the locked/distributable/outstanding # values assert_synched_channels( channel0, balance0, [locked_transfer.lock], channel1, balance1, [], ) channel0.claim_locked(secret) channel1.claim_locked(secret) # upon revelation of the secret both balances are updated assert_synched_channels( channel0, balance0 - amount, [], channel1, balance1 + amount, [], )
def test_setup(): apps = create_network(num_nodes=2, num_assets=1, channels_per_node=1) app0, app1 = apps # pylint: disable=unbalanced-tuple-unpacking channel0 = app0.raiden.chain.nettingaddresses_by_asset_participant( app0.raiden.chain.asset_addresses[0], app0.raiden.address, ) channel1 = app0.raiden.chain.nettingaddresses_by_asset_participant( app0.raiden.chain.asset_addresses[0], app1.raiden.address, ) assert channel0 and channel1 assert app0.raiden.assetmanagers.keys() == app1.raiden.assetmanagers.keys() assert len(app0.raiden.assetmanagers) == 1
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 transfer_speed(num_transfers=100, max_locked=100): # pylint: disable=too-many-locals channels_per_node = 1 deposit = 100 num_nodes = 2 num_assets = 1 private_keys = [ sha3('speed:{}'.format(position)) for position in range(num_nodes) ] assets = [ sha3('asset:{}'.format(number))[:20] for number in range(num_assets) ] apps = create_network(private_keys, assets, MOCK_REGISTRY_ADDRESS, channels_per_node, deposit, DEFAULT_SETTLE_TIMEOUT, UDPTransport, BlockChainServiceMock) app0, app1 = apps # pylint: disable=unbalanced-tuple-unpacking channel0 = app0.raiden.assetmanagers.values()[0].channels.values()[0] channel1 = app1.raiden.assetmanagers.values()[0].channels.values()[0] amounts = [a % 100 + 1 for a in range(1, num_transfers + 1)] secrets = [str(i) for i in range(num_transfers)] expiration = app0.raiden.chain.block_number + 100 start = time.time() for i, amount in enumerate(amounts): hashlock = sha3(secrets[i]) locked_transfer = channel0.create_lockedtransfer( amount=amount, expiration=expiration, hashlock=hashlock, ) app0.raiden.sign(locked_transfer) channel0.register_transfer(locked_transfer) channel1.register_transfer(locked_transfer) if i > max_locked: idx = i - max_locked secret = secrets[idx] channel0.claim_locked(secret) channel1.claim_locked(secret) elapsed = time.time() - start print('%d transfers per second' % (num_transfers / elapsed))
def raiden_network(request, assets_addresses, channels_per_node, deposit, settle_timeout, blockchain_services, transport_class): verbosity = request.config.option.verbose raiden_apps = create_network( blockchain_services, assets_addresses, channels_per_node, deposit, settle_timeout, transport_class, verbosity, ) _raiden_cleanup(request, raiden_apps) return raiden_apps
def test_locked_transfer(): """ Simple locked transfer test. """ apps = create_network(num_nodes=2, num_assets=1, channels_per_node=1) app0, app1 = apps # pylint: disable=unbalanced-tuple-unpacking channel0 = app0.raiden.assetmanagers.values()[0].channels.values()[0] channel1 = app1.raiden.assetmanagers.values()[0].channels.values()[0] balance0 = channel0.balance balance1 = channel1.balance amount = 10 expiration = app0.raiden.chain.block_number + 15 # min_locktime <= expiration < contract.lock_time secret = 'secret' hashlock = sha3(secret) locked_transfer = channel0.create_lockedtransfer( amount=amount, expiration=expiration, hashlock=hashlock, ) app0.raiden.sign(locked_transfer) channel0.register_transfer(locked_transfer) channel1.register_transfer(locked_transfer) # don't update balances but update the locked/distributable/outstanding # values assert_synched_channels( channel0, balance0, [locked_transfer.lock], channel1, balance1, [], ) channel0.claim_locked(secret) channel1.claim_locked(secret) # upon revelation of the secret both balances are updated assert_synched_channels( channel0, balance0 - amount, [], channel1, balance1 + amount, [], )
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_transfer(): apps = create_network(num_nodes=2, num_assets=1, channels_per_node=1) app0, app1 = apps # pylint: disable=unbalanced-tuple-unpacking channel0 = app0.raiden.assetmanagers.values()[0].channels.values()[0] channel1 = app1.raiden.assetmanagers.values()[0].channels.values()[0] initial_balance0 = channel0.initial_balance initial_balance1 = channel1.initial_balance # check agreement on addresses address0 = channel0.our_state.address address1 = channel1.our_state.address assert channel0.asset_address == channel1.asset_address assert app0.raiden.assetmanagers.keys()[0] == app1.raiden.assetmanagers.keys()[0] assert app0.raiden.assetmanagers.values()[0].channels.keys()[0] == app1.raiden.address assert app1.raiden.assetmanagers.values()[0].channels.keys()[0] == app0.raiden.address # check balances of channel and contract are equal details0 = app0.raiden.chain.netting_contract_detail( channel0.asset_address, channel0.nettingcontract_address, address0, ) details1 = app0.raiden.chain.netting_contract_detail( channel1.asset_address, channel1.nettingcontract_address, address1, ) assert initial_balance0 == details0['our_balance'] assert initial_balance1 == details1['our_balance'] assert_synched_channels( channel0, initial_balance0, [], channel1, initial_balance1, [], ) amount = 10 direct_transfer = channel0.create_directtransfer(amount=amount) app0.raiden.sign(direct_transfer) channel0.register_transfer(direct_transfer) channel1.register_transfer(direct_transfer) # check the contract is intact assert details0 == app0.raiden.chain.netting_contract_detail( channel0.asset_address, channel0.nettingcontract_address, address0, ) assert details1 == app0.raiden.chain.netting_contract_detail( channel1.asset_address, channel1.nettingcontract_address, address1, ) assert channel0.initial_balance == initial_balance0 assert channel1.initial_balance == initial_balance1 assert_synched_channels( channel0, initial_balance0 - amount, [], channel1, initial_balance1 + amount, [], )
def test_register_invalid_transfer(): """ Regression test for registration of invalid transfer. Bhe bug occurred if a transfer with an invalid allowance but a valid secret was registered, when the local end registered the transfer it would "unlock" the partners asset, but the transfer wouldn't be sent because the allowance check failed, leaving the channel in an inconsistent state. """ apps = create_network(num_nodes=2, num_assets=1, channels_per_node=1) app0, app1 = apps # pylint: disable=unbalanced-tuple-unpacking channel0 = app0.raiden.assetmanagers.values()[0].channels.values()[0] channel1 = app1.raiden.assetmanagers.values()[0].channels.values()[0] balance0 = channel0.our_state.balance balance1 = channel1.our_state.balance amount = 10 expiration = app0.raiden.chain.block_number + 15 secret = 'secret' hashlock = sha3(secret) transfer1 = channel0.create_lockedtransfer( amount=amount, expiration=expiration, hashlock=hashlock, ) # register a locked transfer app0.raiden.sign(transfer1) channel0.register_transfer(transfer1) channel1.register_transfer(transfer1) # assert the locked transfer is registered assert_synched_channels( channel0, balance0, [transfer1.lock], channel1, balance1, [], ) # handcrafted transfer because channel.create_transfer won't create it transfer2 = DirectTransfer( nonce=channel0.our_state.nonce, asset=channel0.asset_address, balance=channel0.partner_state.balance + balance0 + amount, recipient=channel0.partner_state.address, locksroot=channel0.partner_state.locked.root, secret=secret, ) app0.raiden.sign(transfer2) # this need to fail because the allowance is incorrect with pytest.raises(Exception): channel0.register_transfer(transfer2) with pytest.raises(Exception): channel1.register_transfer(transfer2) # the registration of a bad transfer need fail equaly on both channels assert_synched_channels( channel0, balance0, [transfer1.lock], channel1, balance1, [] )
def test_interwoven_transfers(num=100): # pylint: disable=too-many-locals """ Can keep doing transaction even if not all secrets have been released. """ def log_state(): unclaimed = [ transfer.lock.amount for pos, transfer in enumerate(transfers_list) if not transfers_claimed[pos] ] claimed = [ transfer.lock.amount for pos, transfer in enumerate(transfers_list) if transfers_claimed[pos] ] log.info( 'interwoven', claimed_amount=claimed_amount, distributed_amount=distributed_amount, claimed=claimed, unclaimed=unclaimed, ) apps = create_network(num_nodes=2, num_assets=1, channels_per_node=1) app0, app1 = apps # pylint: disable=unbalanced-tuple-unpacking channel0 = app0.raiden.assetmanagers.values()[0].channels.values()[0] channel1 = app1.raiden.assetmanagers.values()[0].channels.values()[0] initial_balance0 = channel0.initial_balance initial_balance1 = channel1.initial_balance expiration = app0.raiden.chain.block_number + 15 unclaimed_locks = [] transfers_list = [] transfers_amount = [i for i in range(1, num + 1)] # start at 1 because we can't use amount=0 transfers_secret = [str(i) for i in range(num)] transfers_claimed = [] claimed_amount = 0 distributed_amount = 0 for i, (amount, secret) in enumerate(zip(transfers_amount, transfers_secret)): locked_transfer = channel0.create_lockedtransfer( amount=amount, expiration=expiration, hashlock=sha3(secret), ) # synchronized registration app0.raiden.sign(locked_transfer) channel0.register_transfer(locked_transfer) channel1.register_transfer(locked_transfer) # update test state distributed_amount += amount transfers_claimed.append(False) transfers_list.append(locked_transfer) unclaimed_locks.append(locked_transfer.lock) log_state() # test the synchronization and values assert_synched_channels( channel0, initial_balance0 - claimed_amount, unclaimed_locks, channel1, initial_balance1 + claimed_amount, [], ) assert channel0.distributable == initial_balance0 - distributed_amount # claim a transaction at every other iteration, leaving the current one # in place if i > 0 and i % 2 == 0: transfer = transfers_list[i - 1] secret = transfers_secret[i - 1] # synchronized clamining channel0.claim_locked(secret) channel1.claim_locked(secret) # update test state claimed_amount += transfer.lock.amount transfers_claimed[i - 1] = True unclaimed_locks = [ unclaimed_transfer.lock for pos, unclaimed_transfer in enumerate(transfers_list) if not transfers_claimed[pos] ] log_state() # test the state of the channels after the claim assert_synched_channels( channel0, initial_balance0 - claimed_amount, unclaimed_locks, channel1, initial_balance1 + claimed_amount, [], ) assert channel0.distributable == initial_balance0 - distributed_amount
def profile_transfer(num_nodes=10, channels_per_node=2): num_assets = 1 deposit = 10000 assets = [ sha3('asset:{}'.format(number))[:20] for number in range(num_assets) ] private_keys = [ sha3('speed:{}'.format(position)) for position in range(num_nodes) ] BlockChainServiceMock.reset() blockchain_services = list() for privkey in private_keys: blockchain = BlockChainServiceMock( privkey, MOCK_REGISTRY_ADDRESS, ) blockchain_services.append(blockchain) registry = blockchain_services[0].registry(MOCK_REGISTRY_ADDRESS) for asset in assets: registry.add_asset(asset) verbosity = 3 apps = create_network( blockchain_services, assets, channels_per_node, deposit, DEFAULT_SETTLE_TIMEOUT, UDPTransport, verbosity, ) main_app = apps[0] main_api = main_app.raiden.api # channels main_assetmanager = main_app.raiden.get_manager_by_asset_address(assets[0]) # search for a path of length=2 A > B > C num_hops = 2 source = main_app.raiden.address paths = main_assetmanager.channelgraph.get_paths_of_length( source, num_hops) # sanity check assert len(paths) path = paths[0] target = path[-1] # addresses a, b, c = path asset_address = main_assetmanager.asset_address amount = 10 # measure the hot path with profiling.profile(): result = main_api.transfer_async( asset_address, amount, target, 1 # TODO: fill in identifier ) result.wait() profiling.print_all_threads()
def test_interwoven_transfers(num=100): # pylint: disable=too-many-locals """ Can keep doing transaction even if not all secrets have been released. """ def log_state(): unclaimed = [ transfer.lock.amount for pos, transfer in enumerate(transfers_list) if not transfers_claimed[pos] ] claimed = [ transfer.lock.amount for pos, transfer in enumerate(transfers_list) if transfers_claimed[pos] ] log.info( 'interwoven', claimed_amount=claimed_amount, distributed_amount=distributed_amount, claimed=claimed, unclaimed=unclaimed, ) apps = create_network(num_nodes=2, num_assets=1, channels_per_node=1) app0, app1 = apps # pylint: disable=unbalanced-tuple-unpacking channel0 = app0.raiden.assetmanagers.values()[0].channels.values()[0] channel1 = app1.raiden.assetmanagers.values()[0].channels.values()[0] initial_balance0 = channel0.initial_balance initial_balance1 = channel1.initial_balance expiration = app0.raiden.chain.block_number + 15 unclaimed_locks = [] transfers_list = [] transfers_amount = [i for i in range(1, num + 1) ] # start at 1 because we can't use amount=0 transfers_secret = [str(i) for i in range(num)] transfers_claimed = [] claimed_amount = 0 distributed_amount = 0 for i, (amount, secret) in enumerate(zip(transfers_amount, transfers_secret)): locked_transfer = channel0.create_lockedtransfer( amount=amount, expiration=expiration, hashlock=sha3(secret), ) # synchronized registration app0.raiden.sign(locked_transfer) channel0.register_transfer(locked_transfer) channel1.register_transfer(locked_transfer) # update test state distributed_amount += amount transfers_claimed.append(False) transfers_list.append(locked_transfer) unclaimed_locks.append(locked_transfer.lock) log_state() # test the synchronization and values assert_synched_channels( channel0, initial_balance0 - claimed_amount, unclaimed_locks, channel1, initial_balance1 + claimed_amount, [], ) assert channel0.distributable == initial_balance0 - distributed_amount # claim a transaction at every other iteration, leaving the current one # in place if i > 0 and i % 2 == 0: transfer = transfers_list[i - 1] secret = transfers_secret[i - 1] # synchronized clamining channel0.claim_locked(secret) channel1.claim_locked(secret) # update test state claimed_amount += transfer.lock.amount transfers_claimed[i - 1] = True unclaimed_locks = [ unclaimed_transfer.lock for pos, unclaimed_transfer in enumerate(transfers_list) if not transfers_claimed[pos] ] log_state() # test the state of the channels after the claim assert_synched_channels( channel0, initial_balance0 - claimed_amount, unclaimed_locks, channel1, initial_balance1 + claimed_amount, [], ) assert channel0.distributable == initial_balance0 - distributed_amount
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 transfer_speed(num_transfers=100, max_locked=100): # pylint: disable=too-many-locals channels_per_node = 1 num_nodes = 2 num_assets = 1 private_keys = [ sha3('speed:{}'.format(position)) for position in range(num_nodes) ] assets = [ sha3('asset:{}'.format(number))[:20] for number in range(num_assets) ] amounts = [ a % 100 + 1 for a in range(1, num_transfers + 1) ] deposit = sum(amounts) secrets = [ str(i) for i in range(num_transfers) ] BlockChainServiceMock._instance = True blockchain_service = BlockChainServiceMock(None, MOCK_REGISTRY_ADDRESS) BlockChainServiceMock._instance = blockchain_service # pylint: disable=redefined-variable-type registry = blockchain_service.registry(MOCK_REGISTRY_ADDRESS) for asset in assets: registry.add_asset(asset) apps = create_network( private_keys, assets, MOCK_REGISTRY_ADDRESS, channels_per_node, deposit, DEFAULT_SETTLE_TIMEOUT, DEFAULT_POLL_TIMEOUT, UDPTransport, BlockChainServiceMock ) app0, app1 = apps # pylint: disable=unbalanced-tuple-unpacking channel0 = app0.raiden.get_manager_by_asset_address(assets[0]).address_channel.values()[0] channel1 = app1.raiden.get_manager_by_asset_address(assets[0]).address_channel.values()[0] expiration = app0.raiden.chain.block_number() + DEFAULT_REVEAL_TIMEOUT + 3 start = time.time() for i, amount in enumerate(amounts): hashlock = sha3(secrets[i]) locked_transfer = channel0.create_lockedtransfer( amount=amount, identifier=1, # TODO: fill in identifier expiration=expiration, hashlock=hashlock, ) app0.raiden.sign(locked_transfer) channel0.register_transfer(locked_transfer) channel1.register_transfer(locked_transfer) if i > max_locked: idx = i - max_locked secret = secrets[idx] channel0.register_secret(secret) channel1.register_secret(secret) elapsed = time.time() - start print('%d transfers per second' % (num_transfers / elapsed))
def profile_transfer(num_nodes=10, channels_per_node=2): num_assets = 1 deposit = 10000 assets = [ sha3('asset:{}'.format(number))[:20] for number in range(num_assets) ] private_keys = [ sha3('speed:{}'.format(position)) for position in range(num_nodes) ] BlockChainServiceMock.reset() blockchain_services = list() for privkey in private_keys: blockchain = BlockChainServiceMock( privkey, MOCK_REGISTRY_ADDRESS, ) blockchain_services.append(blockchain) registry = blockchain_services[0].registry(MOCK_REGISTRY_ADDRESS) for asset in assets: registry.add_asset(asset) verbosity = 3 apps = create_network( blockchain_services, assets, channels_per_node, deposit, DEFAULT_SETTLE_TIMEOUT, UDPTransport, verbosity, ) main_app = apps[0] main_api = main_app.raiden.api # channels main_assetmanager = main_app.raiden.get_manager_by_asset_address(assets[0]) # search for a path of length=2 A > B > C num_hops = 2 source = main_app.raiden.address paths = main_assetmanager.channelgraph.get_paths_of_length(source, num_hops) # sanity check assert len(paths) path = paths[0] target = path[-1] # addresses a, b, c = path asset_address = main_assetmanager.asset_address amount = 10 # measure the hot path with profiling.profile(): result = main_api.transfer_async( asset_address, amount, target, 1 # TODO: fill in identifier ) result.wait() profiling.print_all_threads()
def test_mediated_transfer(num_transfers=100, num_nodes=10, num_assets=1, channels_per_node=2, deposit=100): # pylint: disable=too-many-locals private_keys = [ sha3('mediated_transfer:{}'.format(position)) for position in range(num_nodes) ] assets = [ sha3('asset:{}'.format(number))[:20] for number in range(num_assets) ] apps = create_network(private_keys, assets, MOCK_REGISTRY_ADDRESS, channels_per_node, deposit, DEFAULT_SETTLE_TIMEOUT, UDPTransport, BlockChainServiceMock) assert len(apps) > num_assets def start_transfers(idx, num_transfers): amount = 10 curr_app = apps[idx] assets = sorted(curr_app.raiden.assetmanagers.keys()) curr_asset = assets[idx] asset_manager = curr_app.raiden.assetmanagers[curr_asset] # search for a path of length=2 A > B > C num_hops = 2 source = curr_app.raiden.address all_paths = asset_manager.channelgraph.get_paths_of_length( source, num_hops) assert len(all_paths) for path in all_paths: assert len(path) == num_hops + 1 assert path[0] == source path = all_paths[0] target = path[-1] shortest_path_length = min( len(path) for path in asset_manager.channelgraph.get_shortest_paths( source, target)) assert path in asset_manager.channelgraph.get_shortest_paths( source, target) assert shortest_path_length == num_hops + 1 finished = gevent.event.Event() def _completion_cb(task, success): _completion_cb.num_transfers -= 1 if _completion_cb.num_transfers > 0: curr_app.raiden.api.transfer(curr_asset, amount, target) else: finished.set() _completion_cb.num_transfers = num_transfers assetmanagers_by_address = { node.raiden.address: node.raiden.assetmanagers for node in apps } next_hop = path[1] next_assetmanager = assetmanagers_by_address[next_hop][curr_asset] next_assetmanager.transfermanager.on_task_completed_callbacks.append( _completion_cb) curr_app.raiden.api.transfer(curr_asset, amount, target) return finished start_time = time.time() finished_events = [] assert num_assets <= num_nodes # Start all transfers for i in range(num_assets): print('finished {}'.format(i)) finished = start_transfers(i, num_transfers) finished_events.append(finished) # Wait until all transfers are done gevent.wait(finished_events) elapsed = time.time() - start_time completed_transfers = num_transfers * num_assets tps = completed_transfers / elapsed print('Completed {} transfers at {} tps'.format(completed_transfers, tps))
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 # 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)) chain0.close( asset_address, nettingcontract_address, app0.raiden.address, transfermessage, None, ) unlocked = [(merkle_proof, transfermessage.lock, secret)] chain0.unlock( asset_address, nettingcontract_address, app0.raiden.address, unlocked, ) for _ in range(NettingChannelContract.settle_timeout): chain0.next_block() chain0.settle(asset_address, nettingcontract_address)
def test_transfer(): apps = create_network(num_nodes=2, num_assets=1, channels_per_node=1) app0, app1 = apps # pylint: disable=unbalanced-tuple-unpacking channel0 = app0.raiden.assetmanagers.values()[0].channels.values()[0] channel1 = app1.raiden.assetmanagers.values()[0].channels.values()[0] initial_balance0 = channel0.initial_balance initial_balance1 = channel1.initial_balance # check agreement on addresses address0 = channel0.our_state.address address1 = channel1.our_state.address assert channel0.asset_address == channel1.asset_address assert app0.raiden.assetmanagers.keys( )[0] == app1.raiden.assetmanagers.keys()[0] assert app0.raiden.assetmanagers.values()[0].channels.keys( )[0] == app1.raiden.address assert app1.raiden.assetmanagers.values()[0].channels.keys( )[0] == app0.raiden.address # check balances of channel and contract are equal details0 = app0.raiden.chain.netting_contract_detail( channel0.asset_address, channel0.nettingcontract_address, address0, ) details1 = app0.raiden.chain.netting_contract_detail( channel1.asset_address, channel1.nettingcontract_address, address1, ) assert initial_balance0 == details0['our_balance'] assert initial_balance1 == details1['our_balance'] assert_synched_channels( channel0, initial_balance0, [], channel1, initial_balance1, [], ) amount = 10 direct_transfer = channel0.create_directtransfer(amount=amount) app0.raiden.sign(direct_transfer) channel0.register_transfer(direct_transfer) channel1.register_transfer(direct_transfer) # check the contract is intact assert details0 == app0.raiden.chain.netting_contract_detail( channel0.asset_address, channel0.nettingcontract_address, address0, ) assert details1 == app0.raiden.chain.netting_contract_detail( channel1.asset_address, channel1.nettingcontract_address, address1, ) assert channel0.initial_balance == initial_balance0 assert channel1.initial_balance == initial_balance1 assert_synched_channels( channel0, initial_balance0 - amount, [], channel1, initial_balance1 + amount, [], )
def test_register_invalid_transfer(): """ Regression test for registration of invalid transfer. The bug occurred if a transfer with an invalid allowance but a valid secret was registered, when the local end registered the transfer it would "unlock" the partners asset, but the transfer wouldn't be sent because the allowance check failed, leaving the channel in an inconsistent state. """ apps = create_network(num_nodes=2, num_assets=1, channels_per_node=1) app0, app1 = apps # pylint: disable=unbalanced-tuple-unpacking channel0 = app0.raiden.assetmanagers.values()[0].channels.values()[0] channel1 = app1.raiden.assetmanagers.values()[0].channels.values()[0] balance0 = channel0.balance balance1 = channel1.balance amount = 10 expiration = app0.raiden.chain.block_number + 15 secret = 'secret' hashlock = sha3(secret) transfer1 = channel0.create_lockedtransfer( amount=amount, expiration=expiration, hashlock=hashlock, ) # register a locked transfer app0.raiden.sign(transfer1) channel0.register_transfer(transfer1) channel1.register_transfer(transfer1) # assert the locked transfer is registered assert_synched_channels( channel0, balance0, [transfer1.lock], channel1, balance1, [], ) # handcrafted transfer because channel.create_transfer won't create it transfer2 = DirectTransfer( nonce=channel0.our_state.nonce, asset=channel0.asset_address, transfered_amount=channel1.balance + balance0 + amount, recipient=channel0.partner_state.address, locksroot=channel0.partner_state.locked.root, secret=secret, ) app0.raiden.sign(transfer2) # this need to fail because the allowance is incorrect with pytest.raises(Exception): channel0.register_transfer(transfer2) with pytest.raises(Exception): channel1.register_transfer(transfer2) # the registration of a bad transfer need fail equaly on both channels assert_synched_channels(channel0, balance0, [transfer1.lock], channel1, balance1, [])
def transfer_speed(num_transfers=100, max_locked=100): # pylint: disable=too-many-locals channels_per_node = 1 num_nodes = 2 num_tokens = 1 private_keys = [ sha3('speed:{}'.format(position)) for position in range(num_nodes) ] tokens = [ sha3('token:{}'.format(number))[:20] for number in range(num_tokens) ] amounts = [a % 100 + 1 for a in range(1, num_transfers + 1)] deposit = sum(amounts) secrets = [str(i) for i in range(num_transfers)] blockchain_services = list() tester = tester_state( private_keys[0], private_keys, tester_blockgas_limit(), ) nettingchannel_library_address = tester_nettingchannel_library_address( tester_state, ) channelmanager_library_address = tester_channelmanager_library_address( tester_state, nettingchannel_library_address, ) registry_address = tester_registry_address( tester_state, channelmanager_library_address, ) for privkey in private_keys: blockchain = BlockChainServiceTesterMock( privkey, tester, registry_address, ) blockchain_services.append(blockchain) registry = blockchain_services[0].registry(registry_address) for token in tokens: registry.add_token(token) apps = create_network( private_keys, tokens, registry_address, channels_per_node, deposit, DEFAULT_SETTLE_TIMEOUT, DEFAULT_POLL_TIMEOUT, UDPTransport, BlockChainServiceTesterMock, ) app0, app1 = apps # pylint: disable=unbalanced-tuple-unpacking channel0 = app0.raiden.channelgraphs[tokens[0]].address_channel.values()[0] channel1 = app1.raiden.channelgraphs[tokens[0]].address_channel.values()[0] expiration = app0.raiden.chain.block_number() + DEFAULT_REVEAL_TIMEOUT + 3 start = time.time() for i, amount in enumerate(amounts): hashlock = sha3(secrets[i]) locked_transfer = channel0.create_lockedtransfer( app0.raiden.get_block_number(), amount=amount, identifier=1, # TODO: fill in identifier expiration=expiration, hashlock=hashlock, ) app0.raiden.sign(locked_transfer) channel0.register_transfer(locked_transfer) channel1.register_transfer(locked_transfer) if i > max_locked: idx = i - max_locked secret = secrets[idx] channel0.register_secret(secret) channel1.register_secret(secret) elapsed = time.time() - start print('%d transfers per second' % (num_transfers / elapsed))
def transfer_speed(num_transfers=100, max_locked=100): # pylint: disable=too-many-locals channels_per_node = 1 num_nodes = 2 num_tokens = 1 private_keys = [ sha3('speed:{}'.format(position).encode()) for position in range(num_nodes) ] tokens = [ sha3('token:{}'.format(number).encode())[:20] for number in range(num_tokens) ] amounts = [ a % 100 + 1 for a in range(1, num_transfers + 1) ] deposit = sum(amounts) secrets = [ str(i) for i in range(num_transfers) ] blockchain_services = list() tester = tester_chain( private_keys[0], private_keys, tester_blockgas_limit(), ) nettingchannel_library_address = tester_nettingchannel_library_address( tester_chain, ) channelmanager_library_address = tester_channelmanager_library_address( tester_chain, nettingchannel_library_address, ) registry_address = tester_registry_address( tester_chain, channelmanager_library_address, ) for privkey in private_keys: blockchain = BlockChainServiceTesterMock( privkey, tester, ) blockchain_services.append(blockchain) registry = blockchain_services[0].registry(registry_address) for token in tokens: registry.add_token(token) apps = create_network( private_keys, tokens, registry_address, channels_per_node, deposit, DEFAULT_SETTLE_TIMEOUT, DEFAULT_POLL_TIMEOUT, UDPTransport, BlockChainServiceTesterMock, ) app0, app1 = apps # pylint: disable=unbalanced-tuple-unpacking channel0 = list(app0.raiden.token_to_channelgraph[tokens[0]].address_to_channel.values())[0] channel1 = list(app1.raiden.token_to_channelgraph[tokens[0]].address_to_channel.values())[0] expiration = app0.raiden.chain.block_number() + DEFAULT_REVEAL_TIMEOUT + 3 start = time.time() for i, amount in enumerate(amounts): hashlock = sha3(secrets[i].encode()) locked_transfer = channel0.create_lockedtransfer( amount=amount, identifier=1, # TODO: fill in identifier expiration=expiration, hashlock=hashlock, ) app0.raiden.sign(locked_transfer) channel0.register_transfer( app0.raiden.get_block_number(), locked_transfer, ) channel1.register_transfer( app0.raiden.get_block_number(), locked_transfer, ) if i > max_locked: idx = i - max_locked secret = secrets[idx] channel0.register_secret(secret) channel1.register_secret(secret) elapsed = time.time() - start print('{} transfers per second'.format(num_transfers / elapsed))