def test_get_privkey(keystore_mock): account_manager = AccountManager(keystore_mock) assert '0xf696ecb5c767263c797a035db6f6008d38d852960ed33a491a58390b003fb605' == encode_hex( account_manager.get_privkey('0d5a0e4fece4b84365b9b8dba6e6d41348c73645', '123'), ) assert '0xf696ecb5c767263c797a035db6f6008d38d852960ed33a491a58390b003fb605' == encode_hex( account_manager.get_privkey( '0x0d5a0e4fece4b84365b9b8dba6e6d41348c73645', '123'), ) assert '0x36fa966441f259501110ba88f8212dfd7f8bacb07862a7d5cf8f31c1a64551e5' == encode_hex( account_manager.get_privkey('3593403033d18b82f7b4a0f18e1ed24623d23b20', '123'), ) assert '0x36fa966441f259501110ba88f8212dfd7f8bacb07862a7d5cf8f31c1a64551e5' == encode_hex( account_manager.get_privkey( '0x3593403033d18b82f7b4a0f18e1ed24623d23b20', '123'), ) # failures with pytest.raises(ValueError) as exc: account_manager.get_privkey( '0x3593403033d18b82f7b4a0f18e1ed24623d23b20', '456') assert 'MAC mismatch' in str(exc.value) with pytest.raises(ValueError) as exc: account_manager.get_privkey('a05934d3033d18b82f7b4adf18e1ed24e3d23b19', '123') assert ( 'Keystore file not found for 0xa05934d3033d18b82f7b4adf18e1ed24e3d23b19' in str(exc.value))
def get_private_key(keystore): accmgr = AccountManager(keystore) if not accmgr.accounts: raise RuntimeError("No Ethereum accounts found in the user's system") addresses = list(accmgr.accounts.keys()) return accmgr.get_privkey(addresses[0], DEFAULT_PASSPHRASE)
def get_private_key(): keystore = os.path.join(os.environ['RST_DATADIR'], 'keystore') accmgr = AccountManager(keystore) if not accmgr.accounts: raise RuntimeError('No Ethereum accounts found in the user\'s system') addresses = list(accmgr.accounts.keys()) return accmgr.get_privkey(addresses[0], TEST_ACCOUNT_PASSWORD)
def matrix_api_shell(address, password, server): am = AccountManager(os.path.expanduser("~/.ethereum/keystore")) signer = LocalSigner(am.get_privkey(to_checksum_address(address), password)) server_name = server.split("//")[1] matrix_password = encode_hex(signer.sign(server_name.encode())) api = GMatrixHttpApi(server) resp = api.login("m.login.password", user=to_normalized_address(address), password=matrix_password) api.token = resp["access_token"] IPython.embed( header=f"Use the `api` object to interact with matrix on {server}.")
def get_login(address, password) -> None: path = os.path.expanduser("~/.ethereum/keystore") if sys.platform.startswith("darwin"): path = os.path.expanduser("~/Library/Ethereum/keystore") am = AccountManager(path) signer = LocalSigner(am.get_privkey(to_checksum_address(address), password)) print(f"Username: {to_normalized_address(address)}") print("Password:"******"\ttransport {i:02d}:", encode_hex(signer.sign(f"transport{i:02d}.raiden.network".encode())), )
def check_account(account_manager: AccountManager, address_hex: AddressHex) -> None: if not account_manager.address_in_keystore(address_hex): click.secho( f"Account '{address_hex}' could not be found on the system. Aborting ...", fg='red', ) sys.exit(1)
def test_get_account_in_keystore(): account_manager = AccountManager(test_keystore) assert account_manager.address_in_keystore('0d5a0e4fece4b84365b9b8dba6e6d41348c73645') assert account_manager.address_in_keystore('0x0d5a0e4fece4b84365b9b8dba6e6d41348c73645') assert account_manager.address_in_keystore('3593403033d18b82f7b4a0f18e1ed24623d23b20') assert account_manager.address_in_keystore('0x3593403033d18b82f7b4a0f18e1ed24623d23b20') assert not account_manager.address_in_keystore('a05934d3033d18b82f7b4adf18e1ed24e3d23b19')
def unlock_account_with_passwordfile( account_manager: AccountManager, address_hex: AddressHex, password_file: TextIO ) -> PrivateKey: password = password_file.read().strip("\r\n") try: return account_manager.get_privkey(address_hex, password.strip()) except ValueError: raise KeystoreAuthenticationError(f"Incorrect password for {address_hex} in file.")
def test_unlock_account_with_passwordfile(keystore_mock): account_manager = AccountManager(keystore_mock) password_file_path = os.path.join(keystore_mock, "passwordfile.txt") with open(password_file_path, "r") as password_file: privkey = unlock_account_with_passwordfile( account_manager=account_manager, address_hex="0x0d5a0e4FECE4b84365b9B8DbA6e6D41348C73645", password_file=password_file, ) assert privkey
def unlock_account_with_passwordfile(account_manager: AccountManager, address_hex: AddressHex, password_file: TextIO) -> PrivateKey: password = password_file.read().strip("\r\n") try: return account_manager.get_privkey(address_hex, password.strip()) except ValueError: click.secho( f"Incorrect password for {address_hex} in file. Aborting ...", fg="red") sys.exit(1)
def test_get_accounts(test_keystore): account_manager = AccountManager(test_keystore) expected_accounts = { '0d5a0e4fece4b84365b9b8dba6e6d41348c73645': os.path.join( test_keystore, 'UTC--2016-10-26T16-55-53.551024336Z--0d5a0e4fece4b84365b9b8dba6e6d41348c73645' ), '3593403033d18b82f7b4a0f18e1ed24623d23b20': os.path.join(test_keystore, 'valid_keystorefile_with_unexpected_name') } assert expected_accounts == account_manager.accounts
def test_get_accounts(keystore_mock): account_manager = AccountManager(keystore_mock) expected_accounts = { "0x0d5a0e4FECE4b84365b9B8DbA6e6D41348C73645": os.path.join( keystore_mock, "UTC--2016-10-26T16-55-53.551024336Z--0d5a0e4fece4b84365b9b8dba6e6d41348c73645", ), "0x3593403033d18b82f7b4a0F18e1ED24623D23b20": os.path.join( keystore_mock, "valid_keystorefile_with_unexpected_name" ), } assert expected_accounts == account_manager.accounts
def test_get_account_in_keystore(keystore_mock): account_manager = AccountManager(keystore_mock) assert account_manager.address_in_keystore( "0d5a0e4fece4b84365b9b8dba6e6d41348c73645") assert account_manager.address_in_keystore( "0x0d5a0e4fece4b84365b9b8dba6e6d41348c73645") assert account_manager.address_in_keystore( "0x0D5A0E4fece4b84365b9b8dba6e6d41348c73645") assert account_manager.address_in_keystore( "3593403033d18b82f7b4a0f18e1ed24623d23b20") assert account_manager.address_in_keystore( "0x3593403033d18b82f7b4a0f18e1ed24623d23b20") assert not account_manager.address_in_keystore( "a05934d3033d18b82f7b4adf18e1ed24e3d23b19")
def test_account_manager_invalid_directory(caplog): with patch.object(os, 'listdir') as mock_listdir: mock_listdir.side_effect = OSError AccountManager('/some/path') for msg, path, reason in [('Unable to list the specified directory', '/some/path', '')]: for record in caplog.records: message = record.getMessage() if msg in message and path in message and reason in message: break else: assert False, "'{}' not in log messages".format(msg)
def test_account_manager_invalid_files(test_keystore, caplog): with caplog.at_level(logging.DEBUG): AccountManager(test_keystore) for msg, file_name, reason in [ ('Invalid account file', KEYFILE_INVALID, 'Expecting value: line 1 column 1 (char 0)'), ('Can not read account file', KEYFILE_INACCESSIBLE, 'Permission denied') ]: for record in caplog.records: message = record.getMessage() if msg in message and file_name in message and reason in message: break else: assert False, "'{}' not in log messages".format(msg)
def test_account_manager_invalid_directory(caplog): with patch.object(os, "listdir") as mock_listdir: mock_listdir.side_effect = OSError AccountManager("/some/path") logs = [("Unable to list the specified directory", "/some/path", "")] for msg, path, reason in logs: for record in caplog.records: message = record.getMessage() if msg in message and path in message and reason in message: break else: assert False, f"'{msg}' not in log messages"
def test_get_account_in_keystore(keystore_mock): account_manager = AccountManager(keystore_mock) assert account_manager.address_in_keystore( "0x0d5a0e4FECE4b84365b9B8DbA6e6D41348C73645") assert account_manager.address_in_keystore( "0x3593403033d18b82f7b4a0F18e1ED24623D23b20") assert not account_manager.address_in_keystore( "0xa05934d3033D18b82F7b4AdF18E1eD24E3D23b19") assert not account_manager.address_in_keystore(None)
def unlock_account_with_passwordfile( account_manager: AccountManager, address_hex: AddressHex, password_file: io.RawIOBase, ) -> PrivateKey: password = password_file.read() try: return account_manager.get_privkey(address_hex, password) except ValueError: click.secho( f'Incorrect password for {address_hex} in file. Aborting ...', fg='red', ) sys.exit(1)
def test_account_manager_invalid_files(test_keystore, caplog): with caplog.at_level(logging.DEBUG): AccountManager(test_keystore) for msg, file_name, reason in [ ("Invalid account file", KEYFILE_INVALID, "No JSON object"), ("Can not read account file", KEYFILE_INACCESSIBLE, "Permission denied") ]: for record in caplog.records: message = record.getMessage() if msg in message and file_name in message and reason in message: break else: assert False, "'{}' not in log messages".format(msg)
def unlock_account_with_passwordprompt(account_manager: AccountManager, address_hex: AddressHex) -> PrivateKey: tries = 3 for current in range(tries): try: checksum_address = to_checksum_address(address_hex) password = getpass.getpass( f"Enter the password to unlock {checksum_address}: ") return account_manager.get_privkey(address_hex, password) except ValueError: print(f"Incorrect passphrase to unlock the private key. " f"{current} out of {tries} tries. " f"Please try again or kill the process to quit. " f"Usually Ctrl-c.") sys.exit(1)
def test_get_privkey(keystore_mock): account_manager = AccountManager(keystore_mock) assert "0xf696ecb5c767263c797a035db6f6008d38d852960ed33a491a58390b003fb605" == encode_hex( account_manager.get_privkey("0x0d5a0e4FECE4b84365b9B8DbA6e6D41348C73645", "123") ) assert "0x36fa966441f259501110ba88f8212dfd7f8bacb07862a7d5cf8f31c1a64551e5" == encode_hex( account_manager.get_privkey("0x3593403033d18b82f7b4a0F18e1ED24623D23b20", "123") ) # failures with pytest.raises(ValueError) as exc: account_manager.get_privkey("0x3593403033d18b82f7b4a0F18e1ED24623D23b20", "456") assert "MAC mismatch" in str(exc.value) with pytest.raises(KeystoreFileNotFound) as exc: account_manager.get_privkey("0xa05934d3033D18b82F7b4AdF18E1eD24E3D23b19", "123") assert "Keystore file not found for 0xa05934d3033D18b82F7b4AdF18E1eD24E3D23b19" in str( exc.value )
def test_get_privkey(): account_manager = AccountManager(test_keystore) 'f696ecb5c767263c797a035db6f6008d38d852960ed33a491a58390b003fb605' == encode_hex( account_manager.get_privkey('0d5a0e4fece4b84365b9b8dba6e6d41348c73645', '123') ) 'f696ecb5c767263c797a035db6f6008d38d852960ed33a491a58390b003fb605' == encode_hex( account_manager.get_privkey('0x0d5a0e4fece4b84365b9b8dba6e6d41348c73645', '123') ) '36fa966441f259501110ba88f8212dfd7f8bacb07862a7d5cf8f31c1a64551e5' == encode_hex( account_manager.get_privkey('3593403033d18b82f7b4a0f18e1ed24623d23b20', '123') ) '36fa966441f259501110ba88f8212dfd7f8bacb07862a7d5cf8f31c1a64551e5' == encode_hex( account_manager.get_privkey('0x3593403033d18b82f7b4a0f18e1ed24623d23b20', '123') ) # failures with pytest.raises(ValueError) as exc: account_manager.get_privkey('0x3593403033d18b82f7b4a0f18e1ed24623d23b20', '456') assert 'MAC mismatch. Password incorrect?' in exc.value with pytest.raises(ValueError) as exc: account_manager.get_privkey('a05934d3033d18b82f7b4adf18e1ed24e3d23b19', '123') assert 'Keystore file not found for a05934d3033d18b82f7b4adf18e1ed24e3d23b19' in exc.value
def test_account_manager_invalid_files(keystore_mock, caplog): with caplog.at_level(logging.DEBUG): AccountManager(keystore_mock) logs = [ ( "The account file is not valid JSON format", KEYFILE_INVALID, "Expecting value: line 1 column 1 (char 0)", ), ("Can not read account file (errno=13)", KEYFILE_INACCESSIBLE, "Permission denied"), ] for msg, file_name, reason in logs: for record in caplog.records: message = record.getMessage() if msg in message and file_name in message and reason in message: break else: assert False, f"'{msg}' not in log messages"
def unlock_account_with_passwordprompt( account_manager: AccountManager, address_hex: AddressHex, ) -> PrivateKey: tries = 3 for current in range(tries): try: password = getpass.getpass( f'Enter the password to unlock {address_hex}: ', ) return account_manager.get_privkey(address_hex, password) except ValueError: print( f'Incorrect passphrase to unlock the private key. ' f'{current} out of {tries} tries. ' f'Please try again or kill the process to quit. ' f'Usually Ctrl-c.', ) sys.exit(1)
def app(address, keystore_path, eth_rpc_endpoint, registry_contract_address, discovery_contract_address, listen_address, logging, logfile, max_unresponsive_time, send_ping_time): slogging.configure(logging, log_file=logfile) # config_file = args.config_file (listen_host, listen_port) = split_endpoint(listen_address) config = App.default_config.copy() config['host'] = listen_host config['port'] = listen_port config['max_unresponsive_time'] = max_unresponsive_time config['send_ping_time'] = send_ping_time accmgr = AccountManager(keystore_path) if not accmgr.accounts: raise RuntimeError('No Ethereum accounts found in the user\'s system') if not accmgr.address_in_keystore(address): addresses = list(accmgr.accounts.keys()) formatted_addresses = [ '[{:3d}] - 0x{}'.format(idx, addr) for idx, addr in enumerate(addresses) ] should_prompt = True while should_prompt: idx = click.prompt( "The following accounts were found in your machine:\n\n{}" "\nSelect one of them by index to continue: ".format( "\n".join(formatted_addresses)), type=int) if idx >= 0 and idx < len(addresses): should_prompt = False else: print("\nError: Provided index '{}' is out of bounds\n".format( idx)) address = addresses[idx] privatekey = accmgr.get_privkey(address) config['privatekey_hex'] = encode_hex(privatekey) endpoint = eth_rpc_endpoint 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) blockchain_service = BlockChainService( privatekey, decode_hex(registry_contract_address), host=rpc_host, port=rpc_port, ) discovery = ContractDiscovery( blockchain_service.node_address, blockchain_service.discovery(discovery_contract_address)) return App(config, blockchain_service, discovery)
def check_account(account_manager: AccountManager, address_hex: Address) -> None: if not account_manager.address_in_keystore(to_checksum_address(address_hex)): raise RaidenError( f"Account '{address_hex}' could not be found on the system. Aborting ..." )
def run_app( address, keystore_path, gas_price, eth_rpc_endpoint, tokennetwork_registry_contract_address, secret_registry_contract_address, service_registry_contract_address, endpoint_registry_contract_address, user_deposit_contract_address, listen_address, mapped_socket, max_unresponsive_time, api_address, rpc, sync_check, console, password_file, web_ui, datadir, transport, matrix_server, network_id, environment_type, unrecoverable_error_should_crash, pathfinding_service_address, pathfinding_eth_address, pathfinding_max_paths, enable_monitoring, resolver_endpoint, routing_mode, config=None, extra_config=None, **kwargs, ): # pylint: disable=too-many-locals,too-many-branches,too-many-statements,unused-argument from raiden.app import App check_sql_version() if transport == "udp" and not mapped_socket: raise RuntimeError("Missing socket") if datadir is None: datadir = os.path.join(os.path.expanduser("~"), ".raiden") account_manager = AccountManager(keystore_path) check_has_accounts(account_manager) if not address: address_hex = prompt_account(account_manager) else: address_hex = to_normalized_address(address) if password_file: privatekey_bin = unlock_account_with_passwordfile( account_manager=account_manager, address_hex=address_hex, password_file=password_file) else: privatekey_bin = unlock_account_with_passwordprompt( account_manager=account_manager, address_hex=address_hex) address = to_canonical_address(address_hex) (listen_host, listen_port) = split_endpoint(listen_address) (api_host, api_port) = split_endpoint(api_address) config["transport"]["udp"]["host"] = listen_host config["transport"]["udp"]["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 config["resolver_endpoint"] = resolver_endpoint if mapped_socket: config["socket"] = mapped_socket.socket config["transport"]["udp"]["external_ip"] = mapped_socket.external_ip config["transport"]["udp"][ "external_port"] = mapped_socket.external_port config["transport_type"] = transport config["transport"]["matrix"]["server"] = matrix_server config["transport"]["udp"][ "nat_keepalive_retries"] = DEFAULT_NAT_KEEPALIVE_RETRIES timeout = max_unresponsive_time / DEFAULT_NAT_KEEPALIVE_RETRIES config["transport"]["udp"]["nat_keepalive_timeout"] = timeout config[ "unrecoverable_error_should_crash"] = unrecoverable_error_should_crash config["services"]["pathfinding_max_paths"] = pathfinding_max_paths config["services"]["monitoring_enabled"] = enable_monitoring parsed_eth_rpc_endpoint = urlparse(eth_rpc_endpoint) if not parsed_eth_rpc_endpoint.scheme: eth_rpc_endpoint = f"http://{eth_rpc_endpoint}" web3 = Web3(HTTPProvider(eth_rpc_endpoint)) check_ethereum_version(web3) check_network_id(network_id, web3) config["chain_id"] = network_id setup_environment(config, environment_type) contracts = setup_contracts_or_exit(config, network_id) rpc_client = JSONRPCClient( web3, privatekey_bin, gas_price_strategy=gas_price, block_num_confirmations=DEFAULT_NUMBER_OF_BLOCK_CONFIRMATIONS, uses_infura="infura.io" in eth_rpc_endpoint, ) blockchain_service = BlockChainService(jsonrpc_client=rpc_client, contract_manager=ContractManager( config["contracts_path"])) if sync_check: check_synced(blockchain_service) proxies = setup_proxies_or_exit( config=config, tokennetwork_registry_contract_address= tokennetwork_registry_contract_address, secret_registry_contract_address=secret_registry_contract_address, endpoint_registry_contract_address=endpoint_registry_contract_address, user_deposit_contract_address=user_deposit_contract_address, service_registry_contract_address=service_registry_contract_address, blockchain_service=blockchain_service, contracts=contracts, routing_mode=routing_mode, pathfinding_service_address=pathfinding_service_address, pathfinding_eth_address=pathfinding_eth_address, ) database_path = os.path.join( datadir, f"node_{pex(address)}", f"netid_{network_id}", f"network_{pex(proxies.token_network_registry.address)}", f"v{RAIDEN_DB_VERSION}_log.db", ) config["database_path"] = database_path print("\nYou are connected to the '{}' network and the DB path is: {}". format(ID_TO_NETWORKNAME.get(network_id, network_id), database_path)) discovery = None if transport == "udp": transport, discovery = setup_udp_or_exit( config, blockchain_service, address, contracts, endpoint_registry_contract_address) elif transport == "matrix": transport = _setup_matrix(config) else: raise RuntimeError(f'Unknown transport type "{transport}" given') raiden_event_handler = RaidenEventHandler() message_handler = MessageHandler() try: start_block = 0 if "TokenNetworkRegistry" in contracts: start_block = contracts["TokenNetworkRegistry"]["block_number"] raiden_app = App( config=config, chain=blockchain_service, query_start_block=start_block, default_registry=proxies.token_network_registry, default_secret_registry=proxies.secret_registry, default_service_registry=proxies.service_registry, transport=transport, raiden_event_handler=raiden_event_handler, message_handler=message_handler, discovery=discovery, user_deposit=proxies.user_deposit, ) except RaidenError as e: click.secho(f"FATAL: {e}", fg="red") sys.exit(1) try: raiden_app.start() except RuntimeError as e: click.secho(f"FATAL: {e}", fg="red") sys.exit(1) except filelock.Timeout: name_or_id = ID_TO_NETWORKNAME.get(network_id, network_id) click.secho( f"FATAL: Another Raiden instance already running for account {address_hex} on " f"network id {name_or_id}", fg="red", ) sys.exit(1) return raiden_app
def prompt_account(address_hex, keystore_path, password_file): accmgr = AccountManager(keystore_path) if not accmgr.accounts: print( 'No Ethereum accounts found in the provided keystore directory {}. ' 'Please provide a directory containing valid ethereum account ' 'files.'.format(keystore_path), ) sys.exit(1) if not accmgr.address_in_keystore(address_hex): # check if an address has been passed if address_hex is not None: print("Account '{}' could not be found on the system. Aborting ...".format( address_hex)) sys.exit(1) addresses = list(accmgr.accounts.keys()) formatted_addresses = [ '[{:3d}] - {}'.format(idx, to_checksum_address(addr)) for idx, addr in enumerate(addresses) ] should_prompt = True print('The following accounts were found in your machine:') print('') print('\n'.join(formatted_addresses)) print('') while should_prompt: idx = click.prompt('Select one of them by index to continue', type=int) if 0 <= idx < len(addresses): should_prompt = False else: print('\nError: Provided index "{}" is out of bounds\n'.format(idx)) address_hex = addresses[idx] password = None if password_file: password = password_file.read() if password != '': password = password.splitlines()[0] if password is not None: try: privatekey_bin = accmgr.get_privkey(address_hex, password) except ValueError: # ValueError exception raised if the password is incorrect print('Incorrect password for {} in file. Aborting ...'.format(address_hex)) sys.exit(1) else: unlock_tries = 3 while True: try: privatekey_bin = accmgr.get_privkey(address_hex) break except ValueError: # ValueError exception raised if the password is incorrect if unlock_tries == 0: print( 'Exhausted passphrase unlock attempts for {}. Aborting ...' .format(address_hex), ) sys.exit(1) print( 'Incorrect passphrase to unlock the private key. {} tries remaining. ' 'Please try again or kill the process to quit. ' 'Usually Ctrl-c.'.format(unlock_tries), ) unlock_tries -= 1 return address_hex, privatekey_bin
def app( address, # pylint: disable=too-many-arguments,too-many-locals keystore_path, eth_rpc_endpoint, registry_contract_address, discovery_contract_address, listen_address, socket, logging, logfile, max_unresponsive_time, send_ping_time, api_port, rpc, console): slogging.configure(logging, log_file=logfile) # config_file = args.config_file (listen_host, listen_port) = split_endpoint(listen_address) config = App.default_config.copy() config['host'] = listen_host config['port'] = listen_port config['max_unresponsive_time'] = max_unresponsive_time config['send_ping_time'] = send_ping_time config['console'] = console config['rpc'] = rpc config['api_port'] = api_port config['socket'] = socket accmgr = AccountManager(keystore_path) if not accmgr.accounts: raise RuntimeError('No Ethereum accounts found in the user\'s system') if not accmgr.address_in_keystore(address): addresses = list(accmgr.accounts.keys()) formatted_addresses = [ '[{:3d}] - 0x{}'.format(idx, addr) for idx, addr in enumerate(addresses) ] should_prompt = True print('The following accounts were found in your machine:') print('') print('\n'.join(formatted_addresses)) print('') while should_prompt: idx = click.prompt('Select one of them by index to continue', type=int) if idx >= 0 and idx < len(addresses): should_prompt = False else: print("\nError: Provided index '{}' is out of bounds\n".format( idx)) address = addresses[idx] unlock_tries = 3 while True: try: privatekey_bin = accmgr.get_privkey(address) break except ValueError as e: # ValueError exception raised if the password is incorrect if unlock_tries == 0: print( 'Exhausted passphrase unlock attempts for {}. Aborting ...' .format(address)) sys.exit(1) print( 'Incorrect passphrase to unlock the private key. {} tries remaining. ' 'Please try again or kill the process to quit. ' 'Usually Ctrl-c.'.format(unlock_tries)) unlock_tries -= 1 privatekey_hex = privatekey_bin.encode('hex') config['privatekey_hex'] = privatekey_hex endpoint = eth_rpc_endpoint 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) # user may have provided registry and discovery contracts with leading 0x registry_contract_address = address_decoder(registry_contract_address) discovery_contract_address = address_decoder(discovery_contract_address) try: blockchain_service = BlockChainService( privatekey_bin, registry_contract_address, host=rpc_host, port=rpc_port, ) 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) discovery = ContractDiscovery( blockchain_service.node_address, blockchain_service.discovery(discovery_contract_address)) # default database directory raiden_directory = os.path.join(os.path.expanduser('~'), '.raiden') if not os.path.exists(raiden_directory): os.makedirs(raiden_directory) database_path = os.path.join(raiden_directory, 'log.db') config['database_path'] = database_path return App(config, blockchain_service, discovery)
def run_app( address: Address, keystore_path: str, gas_price: Callable, eth_rpc_endpoint: str, user_deposit_contract_address: Optional[UserDepositAddress], api_address: Endpoint, rpc: bool, rpccorsdomain: str, sync_check: bool, console: bool, password_file: TextIO, web_ui: bool, datadir: Optional[str], matrix_server: str, network_id: ChainID, environment_type: Environment, unrecoverable_error_should_crash: bool, pathfinding_service_address: str, pathfinding_max_paths: int, enable_monitoring: bool, resolver_endpoint: str, default_reveal_timeout: BlockTimeout, default_settle_timeout: BlockTimeout, routing_mode: RoutingMode, flat_fee: Tuple[Tuple[TokenAddress, FeeAmount], ...], proportional_fee: Tuple[Tuple[TokenAddress, ProportionalFeeAmount], ...], proportional_imbalance_fee: Tuple[Tuple[TokenAddress, ProportionalFeeAmount], ...], blockchain_query_interval: float, cap_mediation_fees: bool, ** kwargs: Any, # FIXME: not used here, but still receives stuff in smoketest ) -> App: # pylint: disable=too-many-locals,too-many-branches,too-many-statements,unused-argument token_network_registry_deployed_at: Optional[BlockNumber] smart_contracts_start_at: BlockNumber if datadir is None: datadir = os.path.join(os.path.expanduser("~"), ".raiden") account_manager = AccountManager(keystore_path) web3 = Web3(HTTPProvider(rpc_normalized_endpoint(eth_rpc_endpoint))) check_sql_version() check_ethereum_has_accounts(account_manager) check_ethereum_client_is_supported(web3) check_ethereum_network_id(network_id, web3) address, privatekey = get_account_and_private_key(account_manager, address, password_file) api_host, api_port = split_endpoint(api_address) if not api_port: api_port = DEFAULT_HTTP_SERVER_PORT domain_list = [] if rpccorsdomain: if "," in rpccorsdomain: for domain in rpccorsdomain.split(","): domain_list.append(str(domain)) else: domain_list.append(str(rpccorsdomain)) # Set up config fee_config = prepare_mediation_fee_config( cli_token_to_flat_fee=flat_fee, cli_token_to_proportional_fee=proportional_fee, cli_token_to_proportional_imbalance_fee=proportional_imbalance_fee, cli_cap_mediation_fees=cap_mediation_fees, ) rest_api_config = RestApiConfig( rest_api_enabled=rpc, web_ui_enabled=rpc and web_ui, cors_domain_list=domain_list, eth_rpc_endpoint=eth_rpc_endpoint, host=api_host, port=api_port, ) config = RaidenConfig( chain_id=network_id, environment_type=environment_type, reveal_timeout=default_reveal_timeout, settle_timeout=default_settle_timeout, console=console, mediation_fees=fee_config, unrecoverable_error_should_crash=unrecoverable_error_should_crash, resolver_endpoint=resolver_endpoint, rest_api=rest_api_config, ) config.blockchain.query_interval = blockchain_query_interval config.services.monitoring_enabled = enable_monitoring config.services.pathfinding_max_paths = pathfinding_max_paths config.transport.server = matrix_server contracts = load_deployed_contracts_data(config, network_id) rpc_client = JSONRPCClient( web3=web3, privkey=privatekey, gas_price_strategy=gas_price, block_num_confirmations=DEFAULT_NUMBER_OF_BLOCK_CONFIRMATIONS, ) token_network_registry_deployed_at = None if "TokenNetworkRegistry" in contracts: token_network_registry_deployed_at = BlockNumber( contracts[CONTRACT_TOKEN_NETWORK_REGISTRY]["block_number"]) if token_network_registry_deployed_at is None: smart_contracts_start_at = get_smart_contracts_start_at(network_id) else: smart_contracts_start_at = token_network_registry_deployed_at proxy_manager = ProxyManager( rpc_client=rpc_client, contract_manager=ContractManager(config.contracts_path), metadata=ProxyManagerMetadata( token_network_registry_deployed_at= token_network_registry_deployed_at, filters_start_at=smart_contracts_start_at, ), ) api_server: Optional[APIServer] = None if config.rest_api.rest_api_enabled: api_server = start_api_server(rpc_client=rpc_client, config=config.rest_api, eth_rpc_endpoint=eth_rpc_endpoint) if sync_check: check_synced(rpc_client) # The user has the option to launch Raiden with a custom # user deposit contract address. This can be used to load # the addresses for the rest of the deployed contracts. # The steps done here make sure that if a UDC address is provided, # the address has to be valid and all the connected contracts # are configured properly. # If a UDC address was not provided, Raiden would fall back # to using the ones deployed and provided by the raiden-contracts package. if user_deposit_contract_address is not None: if not is_address(user_deposit_contract_address): raise RaidenError("The user deposit address is invalid") deployed_addresses = load_deployment_addresses_from_udc( proxy_manager=proxy_manager, user_deposit_address=user_deposit_contract_address, block_identifier=BLOCK_ID_LATEST, ) else: deployed_addresses = load_deployment_addresses_from_contracts( contracts=contracts) # Load the available matrix servers when no matrix server is given # The list is used in a PFS check if config.transport.server == MATRIX_AUTO_SELECT_SERVER: fetch_available_matrix_servers(config.transport, environment_type) raiden_bundle = raiden_bundle_from_contracts_deployment( proxy_manager=proxy_manager, token_network_registry_address=deployed_addresses. token_network_registry_address, secret_registry_address=deployed_addresses.secret_registry_address, ) services_bundle = services_bundle_from_contracts_deployment( config=config, deployed_addresses=deployed_addresses, proxy_manager=proxy_manager, routing_mode=routing_mode, pathfinding_service_address=pathfinding_service_address, enable_monitoring=enable_monitoring, ) check_ethereum_confirmed_block_is_not_pruned( jsonrpc_client=rpc_client, secret_registry=raiden_bundle.secret_registry, confirmation_blocks=config.blockchain.confirmation_blocks, ) database_path = Path( os.path.join( datadir, f"node_{pex(address)}", f"netid_{network_id}", f"network_{pex(raiden_bundle.token_network_registry.address)}", f"v{RAIDEN_DB_VERSION}_log.db", )) config.database_path = database_path print(f"Raiden is running in {environment_type.value.lower()} mode") print("\nYou are connected to the '{}' network and the DB path is: {}". format(ID_TO_CHAINNAME.get(network_id, network_id), database_path)) matrix_transport = setup_matrix(config.transport, config.services, environment_type, routing_mode) event_handler: EventHandler = RaidenEventHandler() # User should be told how to set fees, if using default fee settings log.debug("Fee Settings", fee_settings=fee_config) has_default_fees = (len(fee_config.token_to_flat_fee) == 0 and len(fee_config.token_to_proportional_fee) == 0 and len(fee_config.token_to_proportional_imbalance_fee) == 0) if has_default_fees: click.secho( "Default fee settings are used. " "If you want use Raiden with mediation fees - flat, proportional and imbalance fees - " "see https://raiden-network.readthedocs.io/en/latest/overview_and_guide.html#firing-it-up", # noqa: E501 fg="yellow", ) # Only send feedback when PFS is used if routing_mode == RoutingMode.PFS: event_handler = PFSFeedbackEventHandler(event_handler) message_handler = MessageHandler() one_to_n_address = (services_bundle.one_to_n.address if services_bundle.one_to_n is not None else None) monitoring_service_address = (services_bundle.monitoring_service.address if services_bundle.monitoring_service is not None else None) raiden_app = App( config=config, rpc_client=rpc_client, proxy_manager=proxy_manager, query_start_block=smart_contracts_start_at, default_registry=raiden_bundle.token_network_registry, default_secret_registry=raiden_bundle.secret_registry, default_service_registry=services_bundle.service_registry, default_user_deposit=services_bundle.user_deposit, default_one_to_n_address=one_to_n_address, default_msc_address=monitoring_service_address, transport=matrix_transport, raiden_event_handler=event_handler, message_handler=message_handler, routing_mode=routing_mode, api_server=api_server, ) raiden_app.start() return raiden_app
def run_app( address, keystore_path, gas_price, eth_rpc_endpoint, tokennetwork_registry_contract_address, secret_registry_contract_address, service_registry_contract_address, endpoint_registry_contract_address, user_deposit_contract_address, listen_address, mapped_socket, max_unresponsive_time, api_address, rpc, sync_check, console, password_file, web_ui, datadir, transport, matrix_server, network_id, environment_type, unrecoverable_error_should_crash, pathfinding_service_address, pathfinding_eth_address, pathfinding_max_paths, enable_monitoring, routing_mode, config=None, extra_config=None, **kwargs, ): # pylint: disable=too-many-locals,too-many-branches,too-many-statements,unused-argument from raiden.app import App _assert_sql_version() if transport == 'udp' and not mapped_socket: raise RuntimeError('Missing socket') if datadir is None: datadir = os.path.join(os.path.expanduser('~'), '.raiden') account_manager = AccountManager(keystore_path) check_has_accounts(account_manager) if not address: address_hex = prompt_account(account_manager) else: address_hex = to_normalized_address(address) if password_file: privatekey_bin = unlock_account_with_passwordfile( account_manager, address_hex, password_file, ) else: privatekey_bin = unlock_account_with_passwordprompt( account_manager, address_hex, ) address = to_canonical_address(address_hex) (listen_host, listen_port) = split_endpoint(listen_address) (api_host, api_port) = split_endpoint(api_address) config['transport']['udp']['host'] = listen_host config['transport']['udp']['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['transport']['udp']['external_ip'] = mapped_socket.external_ip config['transport']['udp'][ 'external_port'] = mapped_socket.external_port config['transport_type'] = transport config['transport']['matrix']['server'] = matrix_server config['transport']['udp'][ 'nat_keepalive_retries'] = DEFAULT_NAT_KEEPALIVE_RETRIES timeout = max_unresponsive_time / DEFAULT_NAT_KEEPALIVE_RETRIES config['transport']['udp']['nat_keepalive_timeout'] = timeout config[ 'unrecoverable_error_should_crash'] = unrecoverable_error_should_crash config['services']['pathfinding_max_paths'] = pathfinding_max_paths config['services']['monitoring_enabled'] = enable_monitoring parsed_eth_rpc_endpoint = urlparse(eth_rpc_endpoint) if not parsed_eth_rpc_endpoint.scheme: eth_rpc_endpoint = f'http://{eth_rpc_endpoint}' web3 = _setup_web3(eth_rpc_endpoint) node_network_id, known_node_network_id = setup_network_id_or_exit( config, network_id, web3) environment_type = setup_environment(config, environment_type) contracts, contract_addresses_known = setup_contracts_or_exit( config, node_network_id) rpc_client = JSONRPCClient( web3, privatekey_bin, gas_price_strategy=gas_price, block_num_confirmations=DEFAULT_NUMBER_OF_BLOCK_CONFIRMATIONS, uses_infura='infura.io' in eth_rpc_endpoint, ) blockchain_service = BlockChainService( jsonrpc_client=rpc_client, contract_manager=ContractManager(config['contracts_path']), ) if sync_check: check_synced(blockchain_service, known_node_network_id) proxies = setup_proxies_or_exit( config=config, tokennetwork_registry_contract_address= tokennetwork_registry_contract_address, secret_registry_contract_address=secret_registry_contract_address, endpoint_registry_contract_address=endpoint_registry_contract_address, user_deposit_contract_address=user_deposit_contract_address, service_registry_contract_address=service_registry_contract_address, contract_addresses_known=contract_addresses_known, blockchain_service=blockchain_service, contracts=contracts, routing_mode=routing_mode, pathfinding_service_address=pathfinding_service_address, pathfinding_eth_address=pathfinding_eth_address, ) database_path = os.path.join( datadir, f'node_{pex(address)}', f'netid_{node_network_id}', f'network_{pex(proxies.token_network_registry.address)}', f'v{RAIDEN_DB_VERSION}_log.db', ) config['database_path'] = database_path print( '\nYou are connected to the \'{}\' network and the DB path is: {}'. format( ID_TO_NETWORKNAME.get(node_network_id, node_network_id), database_path, ), ) discovery = None if transport == 'udp': transport, discovery = setup_udp_or_exit( config, blockchain_service, address, contracts, endpoint_registry_contract_address, ) elif transport == 'matrix': transport = _setup_matrix(config) else: raise RuntimeError(f'Unknown transport type "{transport}" given') raiden_event_handler = RaidenEventHandler() message_handler = MessageHandler() try: start_block = 0 if 'TokenNetworkRegistry' in contracts: start_block = contracts['TokenNetworkRegistry']['block_number'] raiden_app = App( config=config, chain=blockchain_service, query_start_block=start_block, default_registry=proxies.token_network_registry, default_secret_registry=proxies.secret_registry, default_service_registry=proxies.service_registry, transport=transport, raiden_event_handler=raiden_event_handler, message_handler=message_handler, discovery=discovery, user_deposit=proxies.user_deposit, ) except RaidenError as e: click.secho(f'FATAL: {e}', fg='red') sys.exit(1) try: raiden_app.start() except RuntimeError as e: click.secho(f'FATAL: {e}', fg='red') sys.exit(1) except filelock.Timeout: name_or_id = ID_TO_NETWORKNAME.get(node_network_id, node_network_id) click.secho( f'FATAL: Another Raiden instance already running for account {address_hex} on ' f'network id {name_or_id}', fg='red', ) sys.exit(1) return raiden_app
def prompt_account(address_hex, keystore_path, password_file): accmgr = AccountManager(keystore_path) if not accmgr.accounts: raise RuntimeError('No Ethereum accounts found in the user\'s system') if not accmgr.address_in_keystore(address_hex): # check if an address has been passed if address_hex is not None: print( "Account '{}' could not be found on the system. Aborting ...". format(address_hex)) sys.exit(1) addresses = list(accmgr.accounts.keys()) formatted_addresses = [ '[{:3d}] - 0x{}'.format(idx, addr) for idx, addr in enumerate(addresses) ] should_prompt = True print('The following accounts were found in your machine:') print('') print('\n'.join(formatted_addresses)) print('') while should_prompt: idx = click.prompt('Select one of them by index to continue', type=int) if idx >= 0 and idx < len(addresses): should_prompt = False else: print("\nError: Provided index '{}' is out of bounds\n".format( idx)) address_hex = addresses[idx] password = None if password_file: password = password_file.read().splitlines()[0] if password: try: privatekey_bin = accmgr.get_privkey(address_hex, password) except ValueError: # ValueError exception raised if the password is incorrect print('Incorrect password for {} in file. Aborting ...'.format( address_hex)) sys.exit(1) else: unlock_tries = 3 while True: try: privatekey_bin = accmgr.get_privkey(address_hex) break except ValueError: # ValueError exception raised if the password is incorrect if unlock_tries == 0: print( 'Exhausted passphrase unlock attempts for {}. Aborting ...' .format(address_hex)) sys.exit(1) print( 'Incorrect passphrase to unlock the private key. {} tries remaining. ' 'Please try again or kill the process to quit. ' 'Usually Ctrl-c.'.format(unlock_tries)) unlock_tries -= 1 return address_hex, privatekey_bin
def app(address, keystore_path, eth_rpc_endpoint, registry_contract_address, discovery_contract_address, listen_address, logging, logfile, max_unresponsive_time, send_ping_time): slogging.configure(logging, log_file=logfile) # config_file = args.config_file (listen_host, listen_port) = split_endpoint(listen_address) config = App.default_config.copy() config['host'] = listen_host config['port'] = listen_port config['max_unresponsive_time'] = max_unresponsive_time config['send_ping_time'] = send_ping_time accmgr = AccountManager(keystore_path) if not accmgr.accounts: raise RuntimeError('No Ethereum accounts found in the user\'s system') if not accmgr.address_in_keystore(address): addresses = list(accmgr.accounts.keys()) formatted_addresses = [ '[{:3d}] - 0x{}'.format(idx, addr) for idx, addr in enumerate(addresses) ] should_prompt = True while should_prompt: idx = click.prompt( "The following accounts were found in your machine:\n\n{}" "\nSelect one of them by index to continue: ".format( "\n".join(formatted_addresses)), type=int ) if idx >= 0 and idx < len(addresses): should_prompt = False else: print("\nError: Provided index '{}' is out of bounds\n".format(idx)) address = addresses[idx] privatekey = accmgr.get_privkey(address) config['privatekey_hex'] = encode_hex(privatekey) endpoint = eth_rpc_endpoint 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) blockchain_service = BlockChainService( privatekey, decode_hex(registry_contract_address), host=rpc_host, port=rpc_port, ) discovery = ContractDiscovery( blockchain_service, decode_hex(discovery_contract_address) # FIXME: double encoding ) return App(config, blockchain_service, discovery)