def __init__( self, jsonrpc_client: JSONRPCClient, monitoring_service_address: MonitoringServiceAddress, contract_manager: ContractManager, block_identifier: BlockIdentifier, ): if not is_binary_address(monitoring_service_address): raise ValueError("Expected binary address for monitoring service") check_address_has_code_handle_pruned_block( client=jsonrpc_client, address=Address(monitoring_service_address), contract_name=CONTRACT_MONITORING_SERVICE, expected_code=decode_hex( contract_manager.get_runtime_hexcode(CONTRACT_MONITORING_SERVICE) ), given_block_identifier=block_identifier, ) proxy = jsonrpc_client.new_contract_proxy( abi=contract_manager.get_contract_abi(CONTRACT_MONITORING_SERVICE), contract_address=Address(monitoring_service_address), ) self.address = monitoring_service_address self.client = jsonrpc_client self.contract_manager = contract_manager self.node_address = self.client.address self.proxy = proxy
def __init__( self, jsonrpc_client: JSONRPCClient, service_registry_address: ServiceRegistryAddress, contract_manager: ContractManager, block_identifier: BlockIdentifier, ): if not is_binary_address(service_registry_address): raise ValueError("Expected binary address for service registry") self.contract_manager = contract_manager check_address_has_code_handle_pruned_block( client=jsonrpc_client, address=Address(service_registry_address), contract_name=CONTRACT_SERVICE_REGISTRY, expected_code=decode_hex( contract_manager.get_runtime_hexcode( CONTRACT_SERVICE_REGISTRY)), given_block_identifier=block_identifier, ) proxy = jsonrpc_client.new_contract_proxy( abi=self.contract_manager.get_contract_abi( CONTRACT_SERVICE_REGISTRY), contract_address=Address(service_registry_address), ) self.address = service_registry_address self.proxy = proxy self.client = jsonrpc_client self.node_address = self.client.address
def __init__( self, rpc_client: JSONRPCClient, metadata: SmartContractMetadata, proxy_manager: "ProxyManager", block_identifier: BlockIdentifier, ) -> None: check_address_has_code_handle_pruned_block( client=rpc_client, address=Address(metadata.address), contract_name=CONTRACT_TOKEN_NETWORK_REGISTRY, expected_code=metadata.runtime_bytecode, given_block_identifier=block_identifier, ) proxy = rpc_client.new_contract_proxy(abi=metadata.abi, contract_address=Address( metadata.address)) self.address = TokenNetworkRegistryAddress(metadata.address) self.proxy_manager = proxy_manager self.rpc_client = rpc_client self.gas_measurements = metadata.gas_measurements self.metadata = metadata self.node_address = self.rpc_client.address self.proxy = proxy
def __init__( self, jsonrpc_client: JSONRPCClient, one_to_n_address: OneToNAddress, contract_manager: ContractManager, block_identifier: BlockIdentifier, ): if not is_binary_address(one_to_n_address): raise ValueError("Expected binary address for monitoring service") self.contract_manager = contract_manager check_address_has_code_handle_pruned_block( client=jsonrpc_client, address=Address(one_to_n_address), contract_name=CONTRACT_ONE_TO_N, expected_code=decode_hex( contract_manager.get_runtime_hexcode(CONTRACT_ONE_TO_N)), given_block_identifier=block_identifier, ) proxy = jsonrpc_client.new_contract_proxy( abi=self.contract_manager.get_contract_abi(CONTRACT_ONE_TO_N), contract_address=Address(one_to_n_address), ) self.address = one_to_n_address self.proxy = proxy self.client = jsonrpc_client self.node_address = self.client.address
def __init__( self, jsonrpc_client: JSONRPCClient, token_address: TokenAddress, contract_manager: ContractManager, block_identifier: BlockIdentifier, ) -> None: proxy = jsonrpc_client.new_contract_proxy(self.abi(contract_manager), Address(token_address)) if not is_binary_address(token_address): raise ValueError("token_address must be a valid address") check_address_has_code_handle_pruned_block( jsonrpc_client, Address(token_address), "Token", expected_code=None, given_block_identifier=block_identifier, ) self.address = token_address self.client = jsonrpc_client self.node_address = jsonrpc_client.address self.proxy = proxy self.token_lock: RLock = RLock()
def init( self, monitoring_service_address: MonitoringServiceAddress, one_to_n_address: OneToNAddress, given_block_identifier: BlockIdentifier, ) -> None: """ Initialize the UserDeposit contract with MS and OneToN addresses """ check_address_has_code_handle_pruned_block( client=self.client, address=Address(monitoring_service_address), contract_name=CONTRACT_MONITORING_SERVICE, expected_code=decode_hex( self.contract_manager.get_runtime_hexcode(CONTRACT_MONITORING_SERVICE) ), given_block_identifier=given_block_identifier, ) check_address_has_code_handle_pruned_block( client=self.client, address=Address(one_to_n_address), contract_name=CONTRACT_ONE_TO_N, expected_code=decode_hex(self.contract_manager.get_runtime_hexcode(CONTRACT_ONE_TO_N)), given_block_identifier=given_block_identifier, ) try: existing_monitoring_service_address = self.monitoring_service_address( block_identifier=given_block_identifier ) existing_one_to_n_address = self.one_to_n_address( block_identifier=given_block_identifier ) except ValueError: pass except BadFunctionCallOutput: raise_on_call_returned_empty(given_block_identifier) else: if existing_monitoring_service_address != EMPTY_ADDRESS: msg = ( f"MonitoringService contract address is already set to " f"{to_checksum_address(existing_monitoring_service_address)}" ) raise BrokenPreconditionError(msg) if existing_one_to_n_address != EMPTY_ADDRESS: msg = ( f"OneToN contract address is already set to " f"{to_checksum_address(existing_one_to_n_address)}" ) raise BrokenPreconditionError(msg) self._init( monitoring_service_address=monitoring_service_address, one_to_n_address=one_to_n_address, )
def __init__( self, jsonrpc_client: JSONRPCClient, user_deposit_address: UserDepositAddress, contract_manager: ContractManager, proxy_manager: "ProxyManager", block_identifier: BlockIdentifier, ) -> None: if not is_binary_address(user_deposit_address): raise ValueError("Expected binary address format for token nework") check_address_has_code_handle_pruned_block( client=jsonrpc_client, address=Address(user_deposit_address), contract_name=CONTRACT_USER_DEPOSIT, expected_code=decode_hex( contract_manager.get_runtime_hexcode(CONTRACT_USER_DEPOSIT)), given_block_identifier=block_identifier, ) self.client = jsonrpc_client self.address = user_deposit_address self.node_address = self.client.address self.contract_manager = contract_manager self.gas_measurements = gas_measurements( self.contract_manager.contracts_version) self.proxy_manager = proxy_manager self.proxy = jsonrpc_client.new_contract_proxy( abi=self.contract_manager.get_contract_abi(CONTRACT_USER_DEPOSIT), contract_address=Address(user_deposit_address), ) # Keeps track of the current in-flight deposits, to avoid sending # unecessary transactions. self._inflight_deposits: Dict[Address, InflightDeposit] = dict() # Don't allow concurrent withdraw_plan and withdraw calls. # This simplifies the precondition checks. self._withdraw_lock = Lock()
def __init__( self, jsonrpc_client: JSONRPCClient, secret_registry_address: SecretRegistryAddress, contract_manager: ContractManager, block_identifier: BlockIdentifier, ) -> None: if not is_binary_address(secret_registry_address): raise ValueError( "Expected binary address format for secret registry") self.contract_manager = contract_manager check_address_has_code_handle_pruned_block( client=jsonrpc_client, address=Address(secret_registry_address), contract_name=CONTRACT_SECRET_REGISTRY, expected_code=decode_hex( contract_manager.get_runtime_hexcode( CONTRACT_SECRET_REGISTRY)), given_block_identifier=block_identifier, ) proxy = jsonrpc_client.new_contract_proxy( abi=self.contract_manager.get_contract_abi( CONTRACT_SECRET_REGISTRY), contract_address=Address(secret_registry_address), ) # There should be only one smart contract deployed, to avoid race # conditions for on-chain unlocks. self.address = secret_registry_address self.proxy = proxy self.client = jsonrpc_client self.node_address = self.client.address # The dictionary of open transactions is used to avoid sending a # transaction for the same secret more than once. This requires # synchronization for the local threads. self.open_secret_transactions: Dict[Secret, AsyncResult] = dict() self._open_secret_transactions_lock = Semaphore()
def _add_token( self, token_address: TokenAddress, channel_participant_deposit_limit: TokenAmount, token_network_deposit_limit: TokenAmount, log_details: Dict[Any, Any], ) -> Tuple[TransactionHash, TokenNetworkAddress]: token_network_address = None kwargs = { "_token_address": token_address, "_channel_participant_deposit_limit": channel_participant_deposit_limit, "_token_network_deposit_limit": token_network_deposit_limit, } estimated_transaction = self.rpc_client.estimate_gas( self.proxy, "createERC20TokenNetwork", log_details, **kwargs) if estimated_transaction is not None: estimated_transaction.estimated_gas = safe_gas_limit( estimated_transaction.estimated_gas, self.gas_measurements[ "TokenNetworkRegistry createERC20TokenNetwork"], ) transaction_sent = self.rpc_client.transact(estimated_transaction) transaction_mined = self.rpc_client.poll_transaction( transaction_sent) receipt = transaction_mined.receipt if not was_transaction_successfully_mined(transaction_mined): failed_at_blocknumber = BlockNumber(receipt["blockNumber"]) max_token_networks = self.get_max_token_networks( block_identifier=failed_at_blocknumber) token_networks_created = self.get_token_network_created( block_identifier=failed_at_blocknumber) already_registered = self.get_token_network( token_address=token_address, block_identifier=failed_at_blocknumber) deprecation_executor = self.get_deprecation_executor( block_identifier=failed_at_blocknumber) settlement_timeout_min = self.settlement_timeout_min( block_identifier=failed_at_blocknumber) settlement_timeout_max = self.settlement_timeout_max( block_identifier=failed_at_blocknumber) chain_id = self.get_chain_id( block_identifier=failed_at_blocknumber) secret_registry_address = self.get_secret_registry_address( block_identifier=failed_at_blocknumber) try: # Creating a new instance to run the constructor checks. token_proxy = Token( jsonrpc_client=self.rpc_client, token_address=token_address, contract_manager=self.proxy_manager.contract_manager, block_identifier=failed_at_blocknumber, ) except AddressWithoutCode: # This cannot be an unrecoverable error, since the ERC20 # code is external. raise RaidenRecoverableError( "Token disappeared! The address " f"{to_checksum_address(token_address)} did have code at " f"block {log_details['given_block_identifier']}, however " f"at block {failed_at_blocknumber} when the registration " "transaction was mined the address didn't have code " "anymore.") check_transaction_failure(transaction_mined, self.rpc_client) check_address_has_code_handle_pruned_block( client=self.rpc_client, address=Address(secret_registry_address), contract_name=CONTRACT_SECRET_REGISTRY, expected_code=decode_hex( self.proxy_manager.contract_manager. get_runtime_hexcode(CONTRACT_SECRET_REGISTRY)), given_block_identifier=failed_at_blocknumber, ) if token_networks_created >= max_token_networks: raise RaidenRecoverableError( "The number of existing token networks reached the maximum allowed" ) if already_registered: # Race condition lost, the token network was created in a different # transaction which got mined first. raise RaidenRecoverableError( "The token was already registered in the TokenNetworkRegistry." ) if deprecation_executor == NULL_ADDRESS_BYTES: raise RaidenUnrecoverableError( "The deprecation executor property for the " "TokenNetworkRegistry is invalid.") if chain_id == 0: raise RaidenUnrecoverableError( "The chain ID property for the TokenNetworkRegistry is invalid." ) if chain_id != self.rpc_client.chain_id: raise RaidenUnrecoverableError( f"The provided chain ID {chain_id} does not match the " f"network Raiden is running on: {self.rpc_client.chain_id}." ) if secret_registry_address == NULL_ADDRESS_BYTES: raise RaidenUnrecoverableError( "The secret registry address for the token network is invalid." ) if settlement_timeout_min == 0: raise RaidenUnrecoverableError( "The minimum settlement timeout for the token network " "should be larger than zero.") if settlement_timeout_max <= settlement_timeout_min: raise RaidenUnrecoverableError( "The maximum settlement timeout for the token network " "should be larger than the minimum settlement timeout." ) total_supply = token_proxy.total_supply( block_identifier=failed_at_blocknumber) if not total_supply or total_supply <= 0: raise RaidenRecoverableError( f"The given token address is not a valid ERC20 token, " f"total_supply() returned an invalid value {total_supply}." ) # At this point, the TokenNetworkRegistry fails to instantiate # a new TokenNetwork. raise RaidenUnrecoverableError( "createERC20TokenNetwork failed for an unknown reason, even " "though the gas estimation succeeded.") succeeded_at_blockhash = receipt["blockHash"] token_network_address = self.get_token_network( token_address, succeeded_at_blockhash) if token_network_address is None: msg = "createERC20TokenNetwork succeeded but token network address is Null" raise RaidenUnrecoverableError(msg) else: # `estimated_transaction` is None # The latest block can not be used reliably because of reorgs, # therefore every call using this block has to handle pruned data. failed_at_block = self.rpc_client.get_block(BLOCK_ID_LATEST) failed_at_blockhash = failed_at_block["hash"].hex() failed_at_blocknumber = failed_at_block["number"] max_token_networks = self.get_max_token_networks( block_identifier=failed_at_blocknumber) token_networks_created = self.get_token_network_created( block_identifier=failed_at_blocknumber) already_registered = self.get_token_network( token_address=token_address, block_identifier=failed_at_blocknumber) deprecation_executor = self.get_deprecation_executor( block_identifier=failed_at_blocknumber) settlement_timeout_min = self.settlement_timeout_min( block_identifier=failed_at_blocknumber) settlement_timeout_max = self.settlement_timeout_max( block_identifier=failed_at_blocknumber) chain_id = self.get_chain_id( block_identifier=failed_at_blocknumber) secret_registry_address = self.get_secret_registry_address( block_identifier=failed_at_blocknumber) try: # Creating a new instance to run the constructor checks. token_proxy = Token( jsonrpc_client=self.rpc_client, token_address=token_address, contract_manager=self.proxy_manager.contract_manager, block_identifier=failed_at_blocknumber, ) except AddressWithoutCode: # This cannot be an unrecoverable error, since the ERC20 # code is external. raise RaidenRecoverableError( "Token disappeared! The address " "{to_checksum_address(token_address)} did have code at " "block {log_details['given_block_identifier']}, however " "at block {failed_at_blocknumber} when the registration " "transaction was mined the address didn't have code " "anymore.") check_address_has_code_handle_pruned_block( client=self.rpc_client, address=Address(secret_registry_address), contract_name=CONTRACT_SECRET_REGISTRY, expected_code=decode_hex( self.proxy_manager.contract_manager.get_runtime_hexcode( CONTRACT_SECRET_REGISTRY)), given_block_identifier=failed_at_blocknumber, ) required_gas = self.gas_measurements[ "TokenNetworkRegistry createERC20TokenNetwork"] self.rpc_client.check_for_insufficient_eth( transaction_name="createERC20TokenNetwork", transaction_executed=False, required_gas=required_gas, block_identifier=failed_at_blocknumber, ) if token_networks_created >= max_token_networks: raise RaidenRecoverableError( "The number of existing token networks reached the maximum allowed" ) if already_registered: # Race condition lost, the token network was created in a different # transaction which got mined first. raise RaidenRecoverableError( "The token was already registered in the TokenNetworkRegistry." ) if deprecation_executor == NULL_ADDRESS_BYTES: raise RaidenUnrecoverableError( "The deprecation executor property for the TokenNetworkRegistry is invalid." ) if chain_id == 0: raise RaidenUnrecoverableError( "The chain ID property for the TokenNetworkRegistry is invalid." ) if chain_id != self.rpc_client.chain_id: raise RaidenUnrecoverableError( f"The provided chain ID {chain_id} does not match the " f"network Raiden is running on: {self.rpc_client.chain_id}." ) if secret_registry_address == NULL_ADDRESS_BYTES: raise RaidenUnrecoverableError( "The secret registry address for the token network is invalid." ) if settlement_timeout_min <= 0: raise RaidenUnrecoverableError( "The minimum settlement timeout for the token network " "should be larger than zero.") if settlement_timeout_max <= settlement_timeout_min: raise RaidenUnrecoverableError( "The maximum settlement timeout for the token network " "should be larger than the minimum settlement timeout.") total_supply = token_proxy.total_supply( block_identifier=failed_at_blocknumber) if not total_supply or total_supply <= 0: raise RaidenRecoverableError( f"The given token address is not a valid ERC20 token, " f"total_supply() returned an invalid value {total_supply}." ) # At this point, the TokenNetworkRegistry fails to instantiate # a new TokenNetwork. raise RaidenUnrecoverableError( f"createERC20TokenNetwork gas estimation failed for an unknown " f"reason. Reference block {failed_at_blockhash} " f"{failed_at_blocknumber}.") return ( TransactionHash(transaction_mined.transaction_hash), TokenNetworkAddress(token_network_address), )