def _jsonrpc_services(deploy_key, deploy_client, private_keys, verbose, poll_timeout, registry_address=None): # we cannot instantiate BlockChainService without a registry, so first # deploy it directly with a JSONRPCClient if registry_address is None: address = privatekey_to_address(deploy_key) registry_path = get_contract_path('Registry.sol') registry_contracts = compile_file(registry_path, libraries=dict()) log.info('Deploying registry contract') registry_proxy = deploy_client.deploy_solidity_contract( address, 'Registry', registry_contracts, dict(), tuple(), contract_path=registry_path, gasprice=default_gasprice, timeout=poll_timeout, ) registry_address = registry_proxy.address # at this point the blockchain must be running, this will overwrite the # method so even if the client is patched twice, it should work fine patch_send_transaction(deploy_client) deploy_blockchain = BlockChainService(deploy_key, deploy_client) deploy_registry = deploy_blockchain.registry(registry_address) host = '0.0.0.0' blockchain_services = list() for privkey in private_keys: rpc_client = JSONRPCClient( privkey=privkey, host=host, port=deploy_client.port, print_communication=False, ) patch_send_transaction(rpc_client) patch_send_message(rpc_client) blockchain = BlockChainService( privkey, rpc_client, ) blockchain_services.append(blockchain) return BlockchainServices( deploy_registry, deploy_blockchain, blockchain_services, )
def app(address, keystore_path, eth_rpc_endpoint, registry_contract_address, discovery_contract_address, listen_address, rpccorsdomain, mapped_socket, logging, logfile, log_json, max_unresponsive_time, send_ping_time, api_address, rpc, sync_check, console, password_file, web_ui, datadir, eth_client_communication, nat): # pylint: disable=too-many-locals,too-many-branches,too-many-statements,unused-argument from raiden.app import App from raiden.network.rpc.client import BlockChainService (listen_host, listen_port) = split_endpoint(listen_address) (api_host, api_port) = split_endpoint(api_address) config = App.DEFAULT_CONFIG.copy() config['host'] = listen_host config['port'] = listen_port config['console'] = console config['rpc'] = rpc config['web_ui'] = rpc and web_ui config['api_host'] = api_host config['api_port'] = api_port if mapped_socket: config['socket'] = mapped_socket.socket config['external_ip'] = mapped_socket.external_ip config['external_port'] = mapped_socket.external_port else: config['socket'] = None config['external_ip'] = listen_host config['external_port'] = listen_port config['protocol']['nat_keepalive_retries'] = DEFAULT_NAT_KEEPALIVE_RETRIES timeout = max_unresponsive_time / DEFAULT_NAT_KEEPALIVE_RETRIES config['protocol']['nat_keepalive_timeout'] = timeout address_hex = address_encoder(address) if address else None address_hex, privatekey_bin = prompt_account(address_hex, keystore_path, password_file) address = address_decoder(address_hex) privatekey_hex = privatekey_bin.encode('hex') config['privatekey_hex'] = privatekey_hex endpoint = eth_rpc_endpoint # Fallback default port if only an IP address is given rpc_port = 8545 if eth_rpc_endpoint.startswith("http://"): endpoint = eth_rpc_endpoint[len("http://"):] rpc_port = 80 elif eth_rpc_endpoint.startswith("https://"): endpoint = eth_rpc_endpoint[len("https://"):] rpc_port = 443 if ':' not in endpoint: # no port was given in url rpc_host = endpoint else: rpc_host, rpc_port = split_endpoint(endpoint) rpc_client = JSONRPCClient( rpc_host, rpc_port, privatekey_bin, ) # this assumes the eth node is already online patch_send_transaction(rpc_client) patch_send_message(rpc_client) if not check_json_rpc(rpc_client): sys.exit(1) blockchain_service = BlockChainService( privatekey_bin, rpc_client, ) if sync_check: check_synced(blockchain_service) discovery_tx_cost = GAS_PRICE * DISCOVERY_REGISTRATION_GAS while True: balance = blockchain_service.client.balance(address) if discovery_tx_cost <= balance: break print( 'Account has insufficient funds for discovery registration.\n' 'Needed: {} ETH\n' 'Available: {} ETH.\n' 'Please deposit additional funds on this account.' .format(discovery_tx_cost / float(denoms.ether), balance / float(denoms.ether)) ) if not click.confirm('Try again?'): sys.exit(1) registry = blockchain_service.registry( registry_contract_address, ) discovery = ContractDiscovery( blockchain_service.node_address, blockchain_service.discovery(discovery_contract_address) ) if datadir is None: # default database directory raiden_directory = os.path.join(os.path.expanduser('~'), '.raiden') else: raiden_directory = datadir if not os.path.exists(raiden_directory): os.makedirs(raiden_directory) user_db_dir = os.path.join(raiden_directory, address_hex[:8]) if not os.path.exists(user_db_dir): os.makedirs(user_db_dir) database_path = os.path.join(user_db_dir, 'log.db') config['database_path'] = database_path return App( config, blockchain_service, registry, discovery, )
def app(address, keystore_path, eth_rpc_endpoint, registry_contract_address, discovery_contract_address, listen_address, rpccorsdomain, mapped_socket, logging, logfile, log_json, max_unresponsive_time, send_ping_time, api_address, rpc, sync_check, console, password_file, web_ui, datadir, eth_client_communication, nat): # pylint: disable=too-many-locals,too-many-branches,too-many-statements,unused-argument from raiden.app import App from raiden.network.rpc.client import BlockChainService (listen_host, listen_port) = split_endpoint(listen_address) (api_host, api_port) = split_endpoint(api_address) config = App.DEFAULT_CONFIG.copy() config['host'] = listen_host config['port'] = listen_port config['console'] = console config['rpc'] = rpc config['web_ui'] = rpc and web_ui config['api_host'] = api_host config['api_port'] = api_port if mapped_socket: config['socket'] = mapped_socket.socket config['external_ip'] = mapped_socket.external_ip config['external_port'] = mapped_socket.external_port else: config['socket'] = None config['external_ip'] = listen_host config['external_port'] = listen_port config['protocol']['nat_keepalive_retries'] = DEFAULT_NAT_KEEPALIVE_RETRIES timeout = max_unresponsive_time / DEFAULT_NAT_KEEPALIVE_RETRIES config['protocol']['nat_keepalive_timeout'] = timeout address_hex = address_encoder(address) if address else None address_hex, privatekey_bin = prompt_account(address_hex, keystore_path, password_file) privatekey_hex = privatekey_bin.encode('hex') config['privatekey_hex'] = privatekey_hex endpoint = eth_rpc_endpoint # Fallback default port if only an IP address is given rpc_port = 8545 if eth_rpc_endpoint.startswith("http://"): endpoint = eth_rpc_endpoint[len("http://"):] rpc_port = 80 elif eth_rpc_endpoint.startswith("https://"): endpoint = eth_rpc_endpoint[len("https://"):] rpc_port = 443 if ':' not in endpoint: # no port was given in url rpc_host = endpoint else: rpc_host, rpc_port = split_endpoint(endpoint) rpc_client = JSONRPCClient( privkey=privatekey_bin, host=rpc_host, port=rpc_port, print_communication=eth_client_communication, ) # this assumes the eth node is already online patch_send_transaction(rpc_client) patch_send_message(rpc_client) try: blockchain_service = BlockChainService( privatekey_bin, rpc_client, ) except ValueError as e: # ValueError exception raised if: # - The registry contract address doesn't have code, this might happen # if the connected geth process is not synced or if the wrong address # is provided (e.g. using the address from a smart contract deployed on # ropsten with a geth node connected to morden) print(e.message) sys.exit(1) if sync_check: try: net_id = int(blockchain_service.client.call('net_version')) network = ID_TO_NETWORKNAME[net_id] except: # pylint: disable=bare-except print( "Couldn't determine the network the ethereum node is connected to.\n" "Because of this there is not way to determine the latest\n" "block with an oracle, and the events from the ethereum\n" "node cannot be trusted. Giving up.\n") sys.exit(1) url = ETHERSCAN_API.format( network=network, action='eth_blockNumber', ) wait_for_sync( blockchain_service, url=url, tolerance=ORACLE_BLOCKNUMBER_DRIFT_TOLERANCE, sleep=3, ) discovery_tx_cost = GAS_PRICE * DISCOVERY_REGISTRATION_GAS while True: balance = blockchain_service.client.balance(address_hex) if discovery_tx_cost <= balance: break print('Account has insufficient funds for discovery registration.\n' 'Needed: {} ETH\n' 'Available: {} ETH.\n' 'Please deposit additional funds on this account.'.format( discovery_tx_cost / float(denoms.ether), balance / float(denoms.ether))) if not click.confirm('Try again?'): sys.exit(1) registry = blockchain_service.registry(registry_contract_address, ) discovery = ContractDiscovery( blockchain_service.node_address, blockchain_service.discovery(discovery_contract_address)) if datadir is None: # default database directory raiden_directory = os.path.join(os.path.expanduser('~'), '.raiden') else: raiden_directory = datadir if not os.path.exists(raiden_directory): os.makedirs(raiden_directory) user_db_dir = os.path.join(raiden_directory, address_hex[:8]) if not os.path.exists(user_db_dir): os.makedirs(user_db_dir) database_path = os.path.join(user_db_dir, 'log.db') config['database_path'] = database_path return App( config, blockchain_service, registry, discovery, )
def run(privatekey, registry_contract_address, discovery_contract_address, listen_address, logging, logfile, scenario, stage_prefix, results_filename): # pylint: disable=unused-argument # TODO: only enabled logging on "initiators" slogging.configure(logging, log_file=logfile) (listen_host, listen_port) = split_endpoint(listen_address) config = App.DEFAULT_CONFIG.copy() config['host'] = listen_host config['port'] = listen_port config['privatekey_hex'] = privatekey privatekey_bin = decode_hex(privatekey) rpc_client = JSONRPCClient( '127.0.0.1', '8545', privatekey_bin, ) blockchain_service = BlockChainService( privatekey_bin, rpc_client, ) discovery = ContractDiscovery(blockchain_service, decode_hex(discovery_contract_address)) registry = blockchain_service.registry(registry_contract_address) app = App( config, blockchain_service, registry, discovery, ) app.discovery.register( app.raiden.address, listen_host, listen_port, ) app.raiden.register_registry(app.raiden.default_registry.address) if scenario: script = json.load(scenario) tools = ConsoleTools( app.raiden, app.discovery, app.config['settle_timeout'], app.config['reveal_timeout'], ) transfers_by_peer = {} tokens = script['tokens'] token_address = None peer = None our_node = app.raiden.address.encode('hex') log.warning("our address is {}".format(our_node)) for token in tokens: # skip tokens that we're not part of nodes = token['channels'] if our_node not in nodes: continue partner_nodes = [node for node in nodes if node != our_node] # allow for prefunded tokens if 'token_address' in token: token_address = token['token_address'] else: token_address = tools.create_token() transfers_with_amount = token['transfers_with_amount'] # FIXME: in order to do bidirectional channels, only one side # (i.e. only token['channels'][0]) should # open; others should join by calling # raiden.api.deposit, AFTER the channel came alive! # NOTE: leaving unidirectional for now because it most # probably will get to higher throughput log.warning("Waiting for all nodes to come online") api = RaidenAPI(app.raiden) for node in partner_nodes: api.start_health_check_for(node) while True: all_reachable = all( api.get_node_network_state(node) == NODE_NETWORK_REACHABLE for node in partner_nodes) if all_reachable: break gevent.sleep(5) log.warning("All nodes are online") if our_node != nodes[-1]: our_index = nodes.index(our_node) peer = nodes[our_index + 1] tools.register_token(token_address) amount = transfers_with_amount[nodes[-1]] while True: try: app.discovery.get(peer.decode('hex')) break except KeyError: log.warning( "Error: peer {} not found in discovery".format( peer)) time.sleep(random.randrange(30)) while True: try: log.warning("Opening channel with {} for {}".format( peer, token_address)) api.open(token_address, peer) break except KeyError: log.warning( "Error: could not open channel with {}".format( peer)) time.sleep(random.randrange(30)) while True: try: log.warning("Funding channel with {} for {}".format( peer, token_address)) api.deposit(token_address, peer, amount) break except Exception: log.warning( "Error: could not deposit {} for {}".format( amount, peer)) time.sleep(random.randrange(30)) if our_index == 0: last_node = nodes[-1] transfers_by_peer[last_node] = int(amount) else: peer = nodes[-2] if stage_prefix is not None: open('{}.stage1'.format(stage_prefix), 'a').close() log.warning("Done with initialization, waiting to continue...") event = gevent.event.Event() gevent.signal(signal.SIGUSR2, event.set) event.wait() transfer_results = {'total_time': 0, 'timestamps': []} def transfer(token_address, amount_per_transfer, total_transfers, peer, is_async): def transfer_(): log.warning("Making {} transfers to {}".format( total_transfers, peer)) initial_time = time.time() times = [0] * total_transfers for index in xrange(total_transfers): RaidenAPI(app.raiden).transfer( token_address.decode('hex'), amount_per_transfer, peer, ) times[index] = time.time() transfer_results['total_time'] = time.time() - initial_time transfer_results['timestamps'] = times log.warning("Making {} transfers took {}".format( total_transfers, transfer_results['total_time'])) log.warning("Times: {}".format(times)) if is_async: return gevent.spawn(transfer_) else: transfer_() # If sending to multiple targets, do it asynchronously, otherwise # keep it simple and just send to the single target on my thread. if len(transfers_by_peer) > 1: greenlets = [] for peer_, amount in transfers_by_peer.items(): greenlet = transfer(token_address, 1, amount, peer_, True) if greenlet is not None: greenlets.append(greenlet) gevent.joinall(greenlets) elif len(transfers_by_peer) == 1: for peer_, amount in transfers_by_peer.items(): transfer(token_address, 1, amount, peer_, False) log.warning("Waiting for termination") open('{}.stage2'.format(stage_prefix), 'a').close() log.warning("Waiting for transfers to finish, will write results...") event = gevent.event.Event() gevent.signal(signal.SIGUSR2, event.set) event.wait() results = tools.channel_stats_for(token_address, peer) if transfer_results['total_time'] != 0: results['total_time'] = transfer_results['total_time'] if len(transfer_results['timestamps']) > 0: results['timestamps'] = transfer_results['timestamps'] results['channel'] = repr(results['channel']) # FIXME log.warning("Results: {}".format(results)) with open(results_filename, 'w') as fp: json.dump(results, fp, indent=2) open('{}.stage3'.format(stage_prefix), 'a').close() event = gevent.event.Event() gevent.signal(signal.SIGQUIT, event.set) gevent.signal(signal.SIGTERM, event.set) gevent.signal(signal.SIGINT, event.set) event.wait() else: log.warning("No scenario file supplied, doing nothing!") open('{}.stage2'.format(stage_prefix), 'a').close() event = gevent.event.Event() gevent.signal(signal.SIGQUIT, event.set) gevent.signal(signal.SIGTERM, event.set) gevent.signal(signal.SIGINT, event.set) event.wait() app.stop()