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
示例#2
0
    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
示例#3
0
    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
示例#4
0
    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
示例#5
0
    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()
示例#6
0
    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,
        )
示例#7
0
    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()
示例#8
0
    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()
示例#9
0
    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),
        )