def verify_deployed_service_contracts_in_filesystem( web3: Web3, contract_manager: ContractManager, token_address: str, user_deposit_whole_balance_limit: int, ): chain_id = int(web3.version.network) deployment_data = get_contracts_deployed( chain_id=chain_id, version=contract_manager.contracts_version, services=True, ) deployment_file_path = contracts_deployed_path( chain_id=chain_id, version=contract_manager.contracts_version, services=True, ) assert deployment_data is not None if verify_service_contracts_deployment_data( web3=web3, contract_manager=contract_manager, token_address=token_address, user_deposit_whole_balance_limit=user_deposit_whole_balance_limit, deployment_data=deployment_data, ): print( f'Deployment info from {deployment_file_path} has been verified and it is CORRECT.' )
def get_deployment_infos( chain_id: ChainID, contracts_version: str = None, ) -> Dict[str, Any]: try: core_contract_data = get_contracts_deployed( chain_id=chain_id, version=contracts_version, ) service_contract_data = get_contracts_deployed( chain_id=chain_id, version=contracts_version, services=True, ) token_network_registry_info = core_contract_data['contracts'][ CONTRACT_TOKEN_NETWORK_REGISTRY] # noqa monitor_contract_info = service_contract_data['contracts'][ CONTRACT_MONITORING_SERVICE] user_deposit_contract_info = service_contract_data['contracts'][ CONTRACT_USER_DEPOSIT] contracts_start_block = max( 0, min( token_network_registry_info['block_number'], monitor_contract_info['block_number'], user_deposit_contract_info['block_number'], ), ) return { CONTRACT_TOKEN_NETWORK_REGISTRY: token_network_registry_info['address'], CONTRACT_MONITORING_SERVICE: monitor_contract_info['address'], CONTRACT_USER_DEPOSIT: user_deposit_contract_info['address'], START_BLOCK_ID: contracts_start_block, } except ValueError: log.info('No deployed contracts were found at the default registry') return { CONTRACT_TOKEN_NETWORK_REGISTRY: None, CONTRACT_MONITORING_SERVICE: None, CONTRACT_USER_DEPOSIT: None, START_BLOCK_ID: 0, }
def test_deploy_data_all( version: Optional[str], chain_id: int, ): data_services = get_contracts_deployed(chain_id, version, services=True) data_raiden = get_contracts_deployed(chain_id, version, services=False) data_all_computed = merge_deployment_data(data_services, data_raiden) data_all = get_contracts_deployment_info(chain_id, version, module=DeploymentModule.ALL) data_default = get_contracts_deployment_info(chain_id, version, module=DeploymentModule.ALL) assert data_all == data_all_computed assert data_all == data_default for name in RAIDEN_CONTRACT_NAMES + SERVICE_CONTRACT_NAMES: deployed = data_all['contracts'][name] reasonable_deployment_of_a_contract(deployed)
def test_deploy_data_has_fields_raiden( version: Optional[str], chain_id: int, ): data = get_contracts_deployed(chain_id, version, services=False) assert data['contracts_version'] == version if version else CONTRACTS_VERSION assert data['chain_id'] == chain_id contracts = data['contracts'] for name in {'EndpointRegistry', 'TokenNetworkRegistry', 'SecretRegistry'}: deployed = contracts[name] reasonable_deployment_of_a_contract(deployed)
def test_deploy_data_has_fields_services( version: Optional[str], chain_id: int, ): data = get_contracts_deployed(chain_id, version, services=True) assert data['contracts_version'] == version if version else CONTRACTS_VERSION assert data['chain_id'] == chain_id contracts = data['contracts'] for name in {'ServiceRegistry', 'MonitoringService', 'OneToN', 'UserDeposit'}: deployed = contracts[name] reasonable_deployment_of_a_contract(deployed)
def get_default_registry_and_start_block( net_version: int, contracts_version: str, ): try: contract_data = get_contracts_deployed(net_version, contracts_version) token_network_registry_info = contract_data['contracts'][CONTRACT_TOKEN_NETWORK_REGISTRY] registry_address = token_network_registry_info['address'] start_block = max(0, token_network_registry_info['block_number'] - 100) return registry_address, start_block except ValueError: log.error('No deployed contracts were found at the default registry') sys.exit(1)
def test_deploy_data_has_fields_services( version: Optional[str], chain_id: int, ): data = get_contracts_deployed(chain_id, version, services=True) data2 = get_contracts_deployment_info(chain_id, version, module=DeploymentModule.SERVICES) assert data2 == data assert data[ 'contracts_version'] == version if version else CONTRACTS_VERSION assert data['chain_id'] == chain_id contracts = data['contracts'] for name in SERVICE_CONTRACT_NAMES: deployed = contracts[name] reasonable_deployment_of_a_contract(deployed)
def verify_deployed_contracts_in_filesystem(self): chain_id = int(self.web3.version.network) deployment_data = get_contracts_deployed( chain_id=chain_id, version=self.contract_manager.contracts_version, ) deployment_file_path = contracts_deployed_path( chain_id=chain_id, version=self.contract_manager.contracts_version, ) assert deployment_data is not None if self._verify_deployment_data(deployment_data): print( f'Deployment info from {deployment_file_path} has been verified' 'and it is CORRECT.')
def verify_deployed_contracts_in_filesystem( web3: Web3, contract_manager: ContractManager, ): chain_id = int(web3.version.network) deployment_data = get_contracts_deployed( chain_id=chain_id, version=contract_manager.contracts_version, ) deployment_file_path = contracts_deployed_path( chain_id=chain_id, version=contract_manager.contracts_version, ) assert deployment_data is not None if verify_deployment_data(web3, contract_manager, deployment_data): print( f'Deployment info from {deployment_file_path} has been verified and it is CORRECT.' )
def run_app( address, keystore_path, gas_price, eth_rpc_endpoint, tokennetwork_registry_contract_address, secret_registry_contract_address, endpoint_registry_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, 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') address_hex = to_normalized_address(address) if address else None address_hex, privatekey_bin = prompt_account(address_hex, keystore_path, password_file) 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['privatekey_hex'] = encode_hex(privatekey_bin) config[ 'unrecoverable_error_should_crash'] = unrecoverable_error_should_crash config['services'][ 'pathfinding_service_address'] = pathfinding_service_address 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) 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( privatekey_bin=privatekey_bin, jsonrpc_client=rpc_client, # Not giving the contract manager here, but injecting it later # since we first need blockchain service to calculate the network id ) given_network_id = network_id node_network_id = blockchain_service.network_id known_given_network_id = given_network_id in ID_TO_NETWORKNAME known_node_network_id = node_network_id in ID_TO_NETWORKNAME if node_network_id != given_network_id: if known_given_network_id and known_node_network_id: click.secho( f"The chosen ethereum network '{ID_TO_NETWORKNAME[given_network_id]}' " f"differs from the ethereum client '{ID_TO_NETWORKNAME[node_network_id]}'. " "Please update your settings.", fg='red', ) else: click.secho( f"The chosen ethereum network id '{given_network_id}' differs " f"from the ethereum client '{node_network_id}'. " "Please update your settings.", fg='red', ) sys.exit(1) config['chain_id'] = given_network_id # interpret the provided string argument if environment_type == Environment.PRODUCTION: # Safe configuration: restrictions for mainnet apply and matrix rooms have to be private config['environment_type'] = Environment.PRODUCTION config['transport']['matrix']['private_rooms'] = True else: config['environment_type'] = Environment.DEVELOPMENT environment_type = config['environment_type'] print(f'Raiden is running in {environment_type.value.lower()} mode') chain_config = {} contract_addresses_known = False contracts = dict() contracts_version = 'pre_limits' if environment_type == Environment.DEVELOPMENT else None config['contracts_path'] = contracts_precompiled_path(contracts_version) if node_network_id in ID_TO_NETWORKNAME and ID_TO_NETWORKNAME[ node_network_id] != 'smoketest': deployment_data = get_contracts_deployed(node_network_id, contracts_version) not_allowed = ( # for now we only disallow mainnet with test configuration network_id == 1 and environment_type == Environment.DEVELOPMENT) if not_allowed: click.secho( f'The chosen network ({ID_TO_NETWORKNAME[node_network_id]}) is not a testnet, ' 'but the "development" environment was selected.\n' 'This is not allowed. Please start again with a safe environment setting ' '(--environment production).', fg='red', ) sys.exit(1) contracts = deployment_data['contracts'] contract_addresses_known = True blockchain_service.inject_contract_manager( ContractManager(config['contracts_path'])) if sync_check: check_synced(blockchain_service, known_node_network_id) contract_addresses_given = ( tokennetwork_registry_contract_address is not None and secret_registry_contract_address is not None and endpoint_registry_contract_address is not None) if not contract_addresses_given and not contract_addresses_known: click.secho( f"There are no known contract addresses for network id '{given_network_id}'. " "Please provide them on the command line or in the configuration file.", fg='red', ) sys.exit(1) try: token_network_registry = blockchain_service.token_network_registry( tokennetwork_registry_contract_address or to_canonical_address( contracts[CONTRACT_TOKEN_NETWORK_REGISTRY]['address'], ), ) except ContractVersionMismatch as e: handle_contract_version_mismatch(e) except AddressWithoutCode: handle_contract_no_code('token network registry', tokennetwork_registry_contract_address) except AddressWrongContract: handle_contract_wrong_address( 'token network registry', tokennetwork_registry_contract_address, ) try: secret_registry = blockchain_service.secret_registry( secret_registry_contract_address or to_canonical_address( contracts[CONTRACT_SECRET_REGISTRY]['address'], ), ) except ContractVersionMismatch as e: handle_contract_version_mismatch(e) except AddressWithoutCode: handle_contract_no_code('secret registry', secret_registry_contract_address) except AddressWrongContract: handle_contract_wrong_address('secret registry', secret_registry_contract_address) database_path = os.path.join( datadir, f'node_{pex(address)}', f'netid_{given_network_id}', f'network_{pex(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(given_network_id, given_network_id), database_path, ), ) discovery = None if transport == 'udp': transport, discovery = _setup_udp( 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: if 'contracts' in chain_config: start_block = chain_config['contracts']['TokenNetworkRegistry'][ 'block_number'] else: start_block = 0 raiden_app = App( config=config, chain=blockchain_service, query_start_block=start_block, default_registry=token_network_registry, default_secret_registry=secret_registry, transport=transport, raiden_event_handler=raiden_event_handler, message_handler=message_handler, discovery=discovery, ) 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(given_network_id, given_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 run_app( address, keystore_path, gas_price, eth_rpc_endpoint, tokennetwork_registry_contract_address, secret_registry_contract_address, endpoint_registry_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_max_paths, 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') address_hex = to_normalized_address(address) if address else None address_hex, privatekey_bin = prompt_account(address_hex, keystore_path, password_file) 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['privatekey_hex'] = encode_hex(privatekey_bin) config['unrecoverable_error_should_crash'] = unrecoverable_error_should_crash config['services']['pathfinding_service_address'] = pathfinding_service_address config['services']['pathfinding_max_paths'] = pathfinding_max_paths 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) 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( privatekey_bin=privatekey_bin, jsonrpc_client=rpc_client, # Not giving the contract manager here, but injecting it later # since we first need blockchain service to calculate the network id ) given_network_id = network_id node_network_id = blockchain_service.network_id known_given_network_id = given_network_id in ID_TO_NETWORKNAME known_node_network_id = node_network_id in ID_TO_NETWORKNAME if node_network_id != given_network_id: if known_given_network_id and known_node_network_id: click.secho( f"The chosen ethereum network '{ID_TO_NETWORKNAME[given_network_id]}' " f"differs from the ethereum client '{ID_TO_NETWORKNAME[node_network_id]}'. " "Please update your settings.", fg='red', ) else: click.secho( f"The chosen ethereum network id '{given_network_id}' differs " f"from the ethereum client '{node_network_id}'. " "Please update your settings.", fg='red', ) sys.exit(1) config['chain_id'] = given_network_id # interpret the provided string argument if environment_type == Environment.PRODUCTION: # Safe configuration: restrictions for mainnet apply and matrix rooms have to be private config['environment_type'] = Environment.PRODUCTION config['transport']['matrix']['private_rooms'] = True else: config['environment_type'] = Environment.DEVELOPMENT environment_type = config['environment_type'] print(f'Raiden is running in {environment_type.value.lower()} mode') chain_config = {} contract_addresses_known = False contracts = dict() contracts_version = 'pre_limits' if environment_type == Environment.DEVELOPMENT else None config['contracts_path'] = contracts_precompiled_path(contracts_version) if node_network_id in ID_TO_NETWORKNAME and ID_TO_NETWORKNAME[node_network_id] != 'smoketest': deployment_data = get_contracts_deployed(node_network_id, contracts_version) not_allowed = ( # for now we only disallow mainnet with test configuration network_id == 1 and environment_type == Environment.DEVELOPMENT ) if not_allowed: click.secho( f'The chosen network ({ID_TO_NETWORKNAME[node_network_id]}) is not a testnet, ' 'but the "development" environment was selected.\n' 'This is not allowed. Please start again with a safe environment setting ' '(--environment production).', fg='red', ) sys.exit(1) contracts = deployment_data['contracts'] contract_addresses_known = True blockchain_service.inject_contract_manager(ContractManager(config['contracts_path'])) if sync_check: check_synced(blockchain_service, known_node_network_id) contract_addresses_given = ( tokennetwork_registry_contract_address is not None and secret_registry_contract_address is not None and endpoint_registry_contract_address is not None ) if not contract_addresses_given and not contract_addresses_known: click.secho( f"There are no known contract addresses for network id '{given_network_id}'. " "Please provide them on the command line or in the configuration file.", fg='red', ) sys.exit(1) try: token_network_registry = blockchain_service.token_network_registry( tokennetwork_registry_contract_address or to_canonical_address( contracts[CONTRACT_TOKEN_NETWORK_REGISTRY]['address'], ), ) except ContractVersionMismatch as e: handle_contract_version_mismatch(e) except AddressWithoutCode: handle_contract_no_code('token network registry', tokennetwork_registry_contract_address) except AddressWrongContract: handle_contract_wrong_address( 'token network registry', tokennetwork_registry_contract_address, ) try: secret_registry = blockchain_service.secret_registry( secret_registry_contract_address or to_canonical_address( contracts[CONTRACT_SECRET_REGISTRY]['address'], ), ) except ContractVersionMismatch as e: handle_contract_version_mismatch(e) except AddressWithoutCode: handle_contract_no_code('secret registry', secret_registry_contract_address) except AddressWrongContract: handle_contract_wrong_address('secret registry', secret_registry_contract_address) database_path = os.path.join( datadir, f'node_{pex(address)}', f'netid_{given_network_id}', f'network_{pex(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(given_network_id, given_network_id), database_path, ), ) discovery = None if transport == 'udp': transport, discovery = _setup_udp( 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: if 'contracts' in chain_config: start_block = chain_config['contracts']['TokenNetworkRegistry']['block_number'] else: start_block = 0 raiden_app = App( config=config, chain=blockchain_service, query_start_block=start_block, default_registry=token_network_registry, default_secret_registry=secret_registry, transport=transport, raiden_event_handler=raiden_event_handler, message_handler=message_handler, discovery=discovery, ) 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(given_network_id, given_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 verify_deployed_contracts(web3: Web3, contract_manager: ContractManager, deployment_data=None): chain_id = int(web3.version.network) deployment_file_path = None if deployment_data is None: deployment_data = get_contracts_deployed( chain_id, contract_manager.contracts_version) deployment_file_path = contracts_deployed_path( chain_id, contract_manager.contracts_version, ) contracts = deployment_data['contracts'] assert contract_manager.contracts_version == deployment_data[ 'contracts_version'] assert chain_id == deployment_data['chain_id'] endpoint_registry_address = contracts[CONTRACT_ENDPOINT_REGISTRY][ 'address'] endpoint_registry_abi = contract_manager.get_contract_abi( CONTRACT_ENDPOINT_REGISTRY) endpoint_registry = web3.eth.contract( abi=endpoint_registry_abi, address=endpoint_registry_address, ) endpoint_registry = PrivateContract(endpoint_registry) # Check that the deployed bytecode matches the precompiled data blockchain_bytecode = web3.eth.getCode(endpoint_registry_address).hex() compiled_bytecode = contract_manager.contracts[CONTRACT_ENDPOINT_REGISTRY][ 'bin'] # Compiled code contains some additional initial data compared to the blockchain bytecode compiled_bytecode = compiled_bytecode[-len(blockchain_bytecode):] compiled_bytecode = hex(int(compiled_bytecode, 16)) assert blockchain_bytecode == compiled_bytecode # Check blockchain transaction hash & block information receipt = web3.eth.getTransactionReceipt( contracts[CONTRACT_ENDPOINT_REGISTRY]['transaction_hash'], ) assert receipt['blockNumber'] == contracts[CONTRACT_ENDPOINT_REGISTRY]['block_number'], \ f"We have block_number {contracts[CONTRACT_ENDPOINT_REGISTRY]['block_number']} " \ f"instead of {receipt['blockNumber']}" assert receipt['gasUsed'] == contracts[CONTRACT_ENDPOINT_REGISTRY]['gas_cost'], \ f"We have gasUsed {contracts[CONTRACT_ENDPOINT_REGISTRY]['gas_cost']} " \ f"instead of {receipt['gasUsed']}" assert receipt['contractAddress'] == contracts[CONTRACT_ENDPOINT_REGISTRY]['address'], \ f"We have contractAddress {contracts[CONTRACT_ENDPOINT_REGISTRY]['address']} " \ f"instead of {receipt['contractAddress']}" # Check the contract version version = endpoint_registry.functions.contract_version().call().decode() assert version == deployment_data['contracts_version'] print( f'{CONTRACT_ENDPOINT_REGISTRY} at {endpoint_registry_address} ' f'matches the compiled data from contracts.json', ) secret_registry_address = contracts[CONTRACT_SECRET_REGISTRY]['address'] secret_registry_abi = contract_manager.get_contract_abi( CONTRACT_SECRET_REGISTRY) secret_registry = web3.eth.contract( abi=secret_registry_abi, address=secret_registry_address, ) secret_registry = PrivateContract(secret_registry) # Check that the deployed bytecode matches the precompiled data blockchain_bytecode = web3.eth.getCode(secret_registry_address).hex() compiled_bytecode = contract_manager.contracts[CONTRACT_SECRET_REGISTRY][ 'bin'] compiled_bytecode = compiled_bytecode[-len(blockchain_bytecode):] compiled_bytecode = hex(int(compiled_bytecode, 16)) assert blockchain_bytecode == compiled_bytecode # Check blockchain transaction hash & block information receipt = web3.eth.getTransactionReceipt( contracts[CONTRACT_SECRET_REGISTRY]['transaction_hash'], ) assert receipt['blockNumber'] == contracts[CONTRACT_SECRET_REGISTRY]['block_number'], \ f"We have block_number {contracts[CONTRACT_SECRET_REGISTRY]['block_number']} " \ f"instead of {receipt['blockNumber']}" assert receipt['gasUsed'] == contracts[CONTRACT_SECRET_REGISTRY]['gas_cost'], \ f"We have gasUsed {contracts[CONTRACT_SECRET_REGISTRY]['gas_cost']} " \ f"instead of {receipt['gasUsed']}" assert receipt['contractAddress'] == contracts[CONTRACT_SECRET_REGISTRY]['address'], \ f"We have contractAddress {contracts[CONTRACT_SECRET_REGISTRY]['address']} " \ f"instead of {receipt['contractAddress']}" # Check the contract version version = secret_registry.functions.contract_version().call().decode() assert version == deployment_data['contracts_version'] print( f'{CONTRACT_SECRET_REGISTRY} at {secret_registry_address} ' f'matches the compiled data from contracts.json', ) token_registry_address = contracts[CONTRACT_TOKEN_NETWORK_REGISTRY][ 'address'] token_registry_abi = contract_manager.get_contract_abi( CONTRACT_TOKEN_NETWORK_REGISTRY, ) token_network_registry = web3.eth.contract( abi=token_registry_abi, address=token_registry_address, ) token_network_registry = PrivateContract(token_network_registry) # Check that the deployed bytecode matches the precompiled data blockchain_bytecode = web3.eth.getCode(token_registry_address).hex() compiled_bytecode = contract_manager.contracts[ CONTRACT_TOKEN_NETWORK_REGISTRY]['bin'] compiled_bytecode = compiled_bytecode[-len(blockchain_bytecode):] compiled_bytecode = hex(int(compiled_bytecode, 16)) assert blockchain_bytecode == compiled_bytecode # Check blockchain transaction hash & block information receipt = web3.eth.getTransactionReceipt( contracts[CONTRACT_TOKEN_NETWORK_REGISTRY]['transaction_hash'], ) assert receipt['blockNumber'] == contracts[CONTRACT_TOKEN_NETWORK_REGISTRY]['block_number'], \ f"We have block_number {contracts[CONTRACT_TOKEN_NETWORK_REGISTRY]['block_number']} " \ f"instead of {receipt['blockNumber']}" assert receipt['gasUsed'] == contracts[CONTRACT_TOKEN_NETWORK_REGISTRY]['gas_cost'], \ f"We have gasUsed {contracts[CONTRACT_TOKEN_NETWORK_REGISTRY]['gas_cost']} " \ f"instead of {receipt['gasUsed']}" assert receipt['contractAddress'] == contracts[CONTRACT_TOKEN_NETWORK_REGISTRY]['address'], \ f"We have contractAddress {contracts[CONTRACT_TOKEN_NETWORK_REGISTRY]['address']} " \ f"instead of {receipt['contractAddress']}" # Check the contract version version = token_network_registry.functions.contract_version().call( ).decode() assert version == deployment_data['contracts_version'] # Check constructor parameters constructor_arguments = contracts[CONTRACT_TOKEN_NETWORK_REGISTRY][ 'constructor_arguments'] assert to_checksum_address( token_network_registry.functions.secret_registry_address().call(), ) == secret_registry_address assert secret_registry_address == constructor_arguments[0] chain_id = token_network_registry.functions.chain_id().call() assert chain_id == constructor_arguments[1] settlement_timeout_min = token_network_registry.functions.settlement_timeout_min( ).call() settlement_timeout_max = token_network_registry.functions.settlement_timeout_max( ).call() assert settlement_timeout_min == constructor_arguments[2] assert settlement_timeout_max == constructor_arguments[3] print( f'{CONTRACT_TOKEN_NETWORK_REGISTRY} at {token_registry_address} ' f'matches the compiled data from contracts.json', ) if deployment_file_path is not None: print( f'Deployment info from {deployment_file_path} has been verified and it is CORRECT.' )
def verify_deployed_contracts(web3: Web3, contract_manager: ContractManager, deployment_data=None): chain_id = int(web3.version.network) deployment_file_path = None if deployment_data is None: deployment_data = get_contracts_deployed(chain_id, contract_manager.contracts_version) deployment_file_path = contracts_deployed_path( chain_id, contract_manager.contracts_version, ) assert deployment_data is not None assert contract_manager.contracts_version == deployment_data['contracts_version'] assert chain_id == deployment_data['chain_id'] endpoint_registry = verify_deployed_contract( web3, contract_manager, deployment_data, CONTRACT_ENDPOINT_REGISTRY, ) print( f'{CONTRACT_ENDPOINT_REGISTRY} at {endpoint_registry.address} ' f'matches the compiled data from contracts.json', ) secret_registry = verify_deployed_contract( web3, contract_manager, deployment_data, CONTRACT_SECRET_REGISTRY, ) print( f'{CONTRACT_SECRET_REGISTRY} at {secret_registry.address} ' f'matches the compiled data from contracts.json', ) token_network_registry = verify_deployed_contract( web3, contract_manager, deployment_data, CONTRACT_TOKEN_NETWORK_REGISTRY, ) # We need to also check the constructor parameters against the chain constructor_arguments = deployment_data['contracts'][ CONTRACT_TOKEN_NETWORK_REGISTRY ]['constructor_arguments'] assert to_checksum_address( token_network_registry.functions.secret_registry_address().call(), ) == secret_registry.address assert secret_registry.address == constructor_arguments[0] chain_id = token_network_registry.functions.chain_id().call() assert chain_id == constructor_arguments[1] settlement_timeout_min = token_network_registry.functions.settlement_timeout_min().call() settlement_timeout_max = token_network_registry.functions.settlement_timeout_max().call() assert settlement_timeout_min == constructor_arguments[2] assert settlement_timeout_max == constructor_arguments[3] print( f'{CONTRACT_TOKEN_NETWORK_REGISTRY} at {token_network_registry.address} ' f'matches the compiled data from contracts.json', ) if deployment_file_path is not None: print(f'Deployment info from {deployment_file_path} has been verified and it is CORRECT.')
def etherscan_verify_contract( chain_id: int, apikey: str, source_module: str, contract_name: str, ): """ Calls Etherscan API for verifying the Solidity source of a contract. Args: chain_id: EIP-155 chain id of the Ethereum chain apikey: key for calling Etherscan API source_module: a module name to look up contracts_source_path() contract_name: 'TokenNetworkRegistry', 'SecretRegistry' etc. """ etherscan_api = api_of_chain_id[chain_id] deployment_info = get_contracts_deployed( chain_id=chain_id, services=(source_module == 'services'), ) contract_manager = ContractManager(contracts_precompiled_path()) data = post_data_for_etherscan_verification( apikey=apikey, deployment_info=deployment_info['contracts'][contract_name], source=join_sources(source_module, contract_name), contract_name=contract_name, metadata=json.loads( contract_manager.contracts[contract_name]['metadata']), constructor_args=get_constructor_args(deployment_info, contract_name, contract_manager), ) response = requests.post(etherscan_api, data=data) content = json.loads(response.content.decode()) print(content) print( f'Status: {content["status"]}; {content["message"]} ; GUID = {content["result"]}' ) etherscan_url = etherscan_api.replace('api-', '').replace('api', '') etherscan_url += '/verifyContract2?a=' + data['contractaddress'] manual_submission_guide = f"""Usually a manual submission to Etherscan works. Visit {etherscan_url} Use raiden_contracts/deploy/joined.sol.""" if content['status'] == '1': # submission succeeded, obtained GUID guid = content['result'] status = '0' retries = 10 while status == '0' and retries > 0: retries -= 1 r = guid_status(etherscan_api=etherscan_api, guid=guid) status = r['status'] if r['result'] == 'Fail - Unable to verify': raise ValueError(manual_submission_guide) if r['result'] == 'Pass - Verified': return print('Retrying...') sleep(5) raise TimeoutError(manual_submission_guide) else: if content['result'] == 'Contract source code already verified': return else: raise ValueError( 'Etherscan submission failed for an unknown reason\n' + manual_submission_guide, )
def etherscan_verify(chain_id, apikey, guid, contract_name): contract_manager = ContractManager(contracts_precompiled_path()) source_path = contracts_source_path() deployment_info = get_contracts_deployed(chain_id) if chain_id == 3: etherscan_api = 'https://api-ropsten.etherscan.io/api' elif chain_id == 4: etherscan_api = 'https://api-rinkeby.etherscan.io/api' elif chain_id == 42: etherscan_api = 'https://api-kovan.etherscan.io/api' elif chain_id == 1: etherscan_api = 'https://api.etherscan.io/api' if guid: guid_status(etherscan_api, guid) return if contract_name is None or contract_name == CONTRACT_ENDPOINT_REGISTRY: path = source_path['raiden'].joinpath( f'{CONTRACT_ENDPOINT_REGISTRY}.sol') source = path.read_text() constructor_args = '' etherscan_verify_contract( etherscan_api, apikey, contract_manager.contracts[CONTRACT_ENDPOINT_REGISTRY], CONTRACT_ENDPOINT_REGISTRY, deployment_info['contracts'][CONTRACT_ENDPOINT_REGISTRY], source, constructor_args, ) if contract_name is None or contract_name == CONTRACT_SECRET_REGISTRY: path = source_path['raiden'].joinpath( f'{CONTRACT_SECRET_REGISTRY}.sol') source = path.read_text() constructor_args = '' etherscan_verify_contract( etherscan_api, apikey, contract_manager.contracts[CONTRACT_SECRET_REGISTRY], CONTRACT_SECRET_REGISTRY, deployment_info['contracts'][CONTRACT_SECRET_REGISTRY], source, constructor_args, ) if contract_name is None or contract_name == CONTRACT_TOKEN_NETWORK_REGISTRY: source = ( source_path['raiden'].joinpath('Utils.sol').read_text() + source_path['raiden'].joinpath('Token.sol').read_text() + source_path['raiden'].joinpath('lib', 'ECVerify.sol').read_text() + source_path['raiden'].joinpath('SecretRegistry.sol').read_text() + source_path['raiden'].joinpath('TokenNetwork.sol').read_text() + source_path['raiden'].joinpath( 'TokenNetworkRegistry.sol').read_text()) source = 'pragma solidity ^0.4.23;' + source.replace( 'pragma solidity ^0.4.23;', '') source = source.replace('import "raiden/Token.sol";\n', '') source = source.replace('import "raiden/Utils.sol";\n', '') source = source.replace('import "raiden/lib/ECVerify.sol";\n', '') source = source.replace('import "raiden/SecretRegistry.sol";\n', '') source = source.replace('import "raiden/TokenNetwork.sol";\n', '') flatten_path = Path(__file__).parent.joinpath('flatten.sol') flatten_path.open('w').write(source) constructor_arguments = deployment_info['contracts'][ CONTRACT_TOKEN_NETWORK_REGISTRY]['constructor_arguments'] abi = contract_manager.contracts[CONTRACT_TOKEN_NETWORK_REGISTRY][ 'abi'] constructor_types = [ arg['type'] for arg in list(filter(lambda x: x['type'] == 'constructor', abi), )[0]['inputs'] ] constructor_args = encode_abi(constructor_types, constructor_arguments).hex() print('constructor_args', constructor_arguments, constructor_types, constructor_args) etherscan_verify_contract( etherscan_api, apikey, contract_manager.contracts[CONTRACT_TOKEN_NETWORK_REGISTRY], CONTRACT_TOKEN_NETWORK_REGISTRY, deployment_info['contracts'][CONTRACT_TOKEN_NETWORK_REGISTRY], source, constructor_args, )
def main( eth_rpc, registry_address, start_block, port, confirmations, ): # setup logging logging.basicConfig( level=logging.INFO, format='%(asctime)s - %(name)s - %(levelname)s - %(message)s', datefmt='%m-%d %H:%M:%S', ) logging.getLogger('web3').setLevel(logging.INFO) logging.getLogger('urllib3.connectionpool').setLevel(logging.ERROR) log.info("Starting Raiden Metrics Server") try: log.info(f'Starting Web3 client for node at {eth_rpc}') web3 = Web3(HTTPProvider(eth_rpc)) web3.middleware_stack.inject(geth_poa_middleware, layer=0) except ConnectionError: log.error( 'Can not connect to the Ethereum client. Please check that it is running and that ' 'your settings are correct.') sys.exit() with no_ssl_verification(): valid_params_given = is_checksum_address( registry_address) and start_block >= 0 if not valid_params_given: try: chain_id = int(web3.net.version) # use limits for mainnet, pre limits for testnets is_mainnet = chain_id == 1 version = None if is_mainnet else 'pre_limits' contract_data = get_contracts_deployed(int(web3.net.version), version) token_network_registry_info = contract_data['contracts'][ CONTRACT_TOKEN_NETWORK_REGISTRY] # noqa registry_address = token_network_registry_info['address'] start_block = max( 0, token_network_registry_info['block_number'] - 100) except ValueError: log.error( 'Provided registry address or start block are not valid and ' 'no deployed contracts were found') sys.exit(1) try: service = MetricsService( web3=web3, contract_manager=ContractManager(contracts_precompiled_path()), registry_address=registry_address, sync_start_block=start_block, required_confirmations=confirmations, ) # re-enable once deployment works # gevent.spawn(write_topology_task, service) api = NetworkInfoAPI(service) api.run(port=port) print(f'Running metrics endpoint at http://localhost:{port}/json') print('Raiden Status Page backend running...') service.run() except (KeyboardInterrupt, SystemExit): print('Exiting...') finally: if service: log.info('Stopping Raiden Metrics Backend') service.stop() return 0
def verify_deployed_service_contracts( web3: Web3, contract_manager: ContractManager, token_address: str, deployment_data: dict=None, ): chain_id = int(web3.version.network) deployment_file_path = None if deployment_data is None: deployment_data = get_contracts_deployed( chain_id, contract_manager.contracts_version, services=True, ) deployment_file_path = contracts_deployed_path( chain_id, contract_manager.contracts_version, services=True, ) assert deployment_data is not None assert contract_manager.contracts_version == deployment_data['contracts_version'] assert chain_id == deployment_data['chain_id'] service_bundle = verify_deployed_contract( web3, contract_manager, deployment_data, CONTRACT_RAIDEN_SERVICE_BUNDLE, ) # We need to also check the constructor parameters against the chain constructor_arguments = deployment_data['contracts'][ CONTRACT_RAIDEN_SERVICE_BUNDLE ]['constructor_arguments'] assert to_checksum_address( service_bundle.functions.token().call(), ) == token_address assert token_address == constructor_arguments[0] print( f'{CONTRACT_RAIDEN_SERVICE_BUNDLE} at {service_bundle.address} ' f'matches the compiled data from contracts.json', ) monitoring_service = verify_deployed_contract( web3, contract_manager, deployment_data, CONTRACT_MONITORING_SERVICE, ) # We need to also check the constructor parameters against the chain constructor_arguments = deployment_data['contracts'][ CONTRACT_MONITORING_SERVICE ]['constructor_arguments'] assert to_checksum_address( monitoring_service.functions.token().call(), ) == token_address assert token_address == constructor_arguments[0] assert to_checksum_address( monitoring_service.functions.rsb().call(), ) == service_bundle.address assert service_bundle.address == constructor_arguments[1] print( f'{CONTRACT_MONITORING_SERVICE} at {monitoring_service.address} ' f'matches the compiled data from contracts.json', ) if deployment_file_path is not None: print(f'Deployment info from {deployment_file_path} has been verified and it is CORRECT.')
def main( eth_rpc, token_registry_address, endpoint_registry_address, start_block, confirmations, # latest, ): """Main command""" # setup logging logging.basicConfig( level=logging.INFO, format="%(asctime)s %(levelname)s %(message)s", datefmt="%Y%m%d %H:%M:%S", ) log = logging.getLogger(__name__) logging.getLogger("web3").setLevel(logging.INFO) logging.getLogger("urllib3.connectionpool").setLevel(logging.ERROR) log.info("Starting Raiden Metrics Server") try: log.info(f"Starting Web3 client for node at {eth_rpc}") web3 = Web3(HTTPProvider(eth_rpc)) web3.middleware_stack.inject(geth_poa_middleware, layer=0) except ConnectionError: log.error( "Can not connect to the Ethereum client. Please check that it is running and that " "your settings are correct." ) sys.exit() # chain = Net(web3) # log.info(f"Net version = {chain.version}") # # use limits for mainnet, pre limits for testnets # is_mainnet = chain.version == 1 # version = None if is_mainnet else "pre_limits" with no_ssl_verification(): valid_params_given = ( is_checksum_address(token_registry_address) and start_block >= 0 ) if not valid_params_given: # or latest is True try: contract_data = get_contracts_deployed(chain_id=4, version="pre_limits") token_network_registry_info = contract_data["contracts"][ CONTRACT_TOKEN_NETWORK_REGISTRY ] endpoint_registry_info = contract_data["contracts"][ CONTRACT_ENDPOINT_REGISTRY ] token_registry_address = token_network_registry_info["address"] endpoint_registry_address = endpoint_registry_info["address"] start_block = ( min( token_network_registry_info["block_number"], endpoint_registry_info["block_number"], ) - 20 ) except ValueError as ex: log.error(ex) log.error( "Provided registry address or start block are not valid and " "no deployed contracts were found" ) sys.exit(1) token_service = MetricsService( web3=web3, contract_manager=ContractManager( contracts_precompiled_path(version="pre_limits") ), token_registry_address=token_registry_address, endpoint_registry_address=endpoint_registry_address, sync_start_block=start_block, required_confirmations=confirmations, ) token_service.run() sys.exit(0)