예제 #1
0
파일: python.py 프로젝트: frlnx/raiden
    def set_total_channel_deposit(
        self,
        registry_address: typing.PaymentNetworkID,
        token_address: typing.TokenAddress,
        partner_address: typing.Address,
        total_deposit: typing.TokenAmount,
        retry_timeout: typing.NetworkTimeout = DEFAULT_RETRY_TIMEOUT,
    ):
        """ Set the `total_deposit` in the channel with the peer at `partner_address` and the
        given `token_address` in order to be able to do transfers.

        Raises:
            InvalidAddress: If either token_address or partner_address is not
            20 bytes long.
            TransactionThrew: May happen for multiple reasons:
                - If the token approval fails, e.g. the token may validate if
                  account has enough balance for the allowance.
                - The deposit failed, e.g. the allowance did not set the token
                  aside for use and the user spent it before deposit was called.
                - The channel was closed/settled between the allowance call and
                  the deposit call.
            AddressWithoutCode: The channel was settled during the deposit
            execution.
            DepositOverLimit: The total deposit amount is higher than the limit.
        """
        chain_state = views.state_from_raiden(self.raiden)

        token_networks = views.get_token_network_addresses_for(
            chain_state,
            registry_address,
        )
        channel_state = views.get_channelstate_for(
            chain_state,
            registry_address,
            token_address,
            partner_address,
        )

        if not is_binary_address(token_address):
            raise InvalidAddress(
                'Expected binary address format for token in channel deposit')

        if not is_binary_address(partner_address):
            raise InvalidAddress(
                'Expected binary address format for partner in channel deposit'
            )

        if token_address not in token_networks:
            raise UnknownTokenAddress('Unknown token address')

        if channel_state is None:
            raise InvalidAddress(
                'No channel with partner_address for the given token')

        token = self.raiden.chain.token(token_address)
        netcontract_address = channel_state.identifier
        token_network_registry = self.raiden.chain.token_network_registry(
            registry_address)
        token_network_address = token_network_registry.get_token_network(
            token_address)
        token_network_proxy = self.raiden.chain.token_network(
            token_network_address)
        channel_proxy = self.raiden.chain.payment_channel(
            token_network_proxy.address,
            netcontract_address,
        )

        balance = token.balance_of(self.raiden.address)

        if self.raiden.config['network_type'] == NetworkType.MAIN:
            deposit_limit = (token_network_proxy.proxy.contract.functions.
                             channel_participant_deposit_limit().call())
            if total_deposit > deposit_limit:
                raise DepositOverLimit(
                    'The deposit of {} is bigger than the current limit of {}'.
                    format(
                        total_deposit,
                        deposit_limit,
                    ), )

        if total_deposit <= channel_state.our_state.contract_balance:
            # no action required
            return

        addendum = total_deposit - channel_state.our_state.contract_balance

        # If this check succeeds it does not imply the the `deposit` will
        # succeed, since the `deposit` transaction may race with another
        # transaction.
        if not balance >= addendum:
            msg = 'Not enough balance to deposit. {} Available={} Needed={}'.format(
                pex(token_address),
                balance,
                addendum,
            )
            raise InsufficientFunds(msg)

        # If concurrent operations are happening on the channel, fail the request
        with channel_proxy.lock_or_raise():
            # set_total_deposit calls approve
            # token.approve(netcontract_address, addendum)
            channel_proxy.set_total_deposit(total_deposit)

            target_address = self.raiden.address
            waiting.wait_for_participant_newbalance(
                self.raiden,
                registry_address,
                token_address,
                partner_address,
                target_address,
                total_deposit,
                retry_timeout,
            )
예제 #2
0
    def set_total_channel_deposit(
        self,
        registry_address,
        token_address,
        partner_address,
        total_deposit,
        poll_timeout=DEFAULT_POLL_TIMEOUT,
        retry_timeout=DEFAULT_RETRY_TIMEOUT,
    ):
        """ Set the `total_deposit` in the channel with the peer at `partner_address` and the
        given `token_address` in order to be able to do transfers.

        Raises:
            InvalidAddress: If either token_address or partner_address is not
            20 bytes long.
            TransactionThrew: May happen for multiple reasons:
                - If the token approval fails, e.g. the token may validate if
                  account has enough balance for the allowance.
                - The deposit failed, e.g. the allowance did not set the token
                  aside for use and the user spent it before deposit was called.
                - The channel was closed/settled between the allowance call and
                  the deposit call.
            AddressWithoutCode: The channel was settled during the deposit
            execution.
            DepositOverLimit: The total deposit amount is higher than the limit.
        """
        node_state = views.state_from_raiden(self.raiden)

        token_networks = views.get_token_network_addresses_for(
            node_state,
            registry_address,
        )
        channel_state = views.get_channelstate_for(
            node_state,
            registry_address,
            token_address,
            partner_address,
        )

        if not is_binary_address(token_address):
            raise InvalidAddress(
                'Expected binary address format for token in channel deposit')

        if not is_binary_address(partner_address):
            raise InvalidAddress(
                'Expected binary address format for partner in channel deposit'
            )

        if token_address not in token_networks:
            raise UnknownTokenAddress('Unknown token address')

        if channel_state is None:
            raise InvalidAddress(
                'No channel with partner_address for the given token')

        token = self.raiden.chain.token(token_address)
        netcontract_address = channel_state.identifier
        token_network_registry = self.raiden.chain.token_network_registry(
            registry_address)
        token_network_proxy = token_network_registry.token_network_by_token(
            token_address)
        channel_proxy = self.raiden.chain.payment_channel(
            token_network_proxy.address,
            netcontract_address,
        )

        balance = token.balance_of(self.raiden.address)

        deposit_limit = token_network_proxy.proxy.contract.functions.deposit_limit(
        ).call()
        if total_deposit > deposit_limit:
            raise DepositOverLimit(
                'The deposit of {} is bigger than the current limit of {}'.
                format(
                    total_deposit,
                    deposit_limit,
                ), )

        if total_deposit <= channel_state.our_state.contract_balance:
            # no action required
            return

        addendum = total_deposit - channel_state.our_state.contract_balance

        # If this check succeeds it does not imply the the `deposit` will
        # succeed, since the `deposit` transaction may race with another
        # transaction.
        if not balance >= addendum:
            msg = 'Not enough balance to deposit. {} Available={} Needed={}'.format(
                pex(token_address),
                balance,
                addendum,
            )
            raise InsufficientFunds(msg)

        # If concurrent operations are happening on the channel, fail the request
        if not channel_proxy.channel_operations_lock.acquire(blocking=False):
            raise ChannelBusyError(
                f'Channel with id {channel_state.identifier} is '
                f'busy with another ongoing operation', )

        with releasing(channel_proxy.channel_operations_lock):
            # set_total_deposit calls approve
            # token.approve(netcontract_address, addendum)
            channel_proxy.set_total_deposit(total_deposit)

            msg = 'After {} seconds the deposit was not properly processed.'.format(
                poll_timeout, )

            # Wait until the `ChannelNewBalance` event is processed.
            with gevent.Timeout(poll_timeout, EthNodeCommunicationError(msg)):
                target_address = self.raiden.address
                waiting.wait_for_participant_newbalance(
                    self.raiden,
                    registry_address,
                    token_address,
                    partner_address,
                    target_address,
                    total_deposit,
                    retry_timeout,
                )
예제 #3
0
    def set_total_channel_deposit(
        self,
        registry_address: typing.PaymentNetworkID,
        token_address: typing.TokenAddress,
        partner_address: typing.Address,
        total_deposit: typing.TokenAmount,
        retry_timeout: typing.NetworkTimeout = DEFAULT_RETRY_TIMEOUT,
    ):
        """ Set the `total_deposit` in the channel with the peer at `partner_address` and the
        given `token_address` in order to be able to do transfers.

        Raises:
            InvalidAddress: If either token_address or partner_address is not
                20 bytes long.
            TransactionThrew: May happen for multiple reasons:
                - If the token approval fails, e.g. the token may validate if
                account has enough balance for the allowance.
                - The deposit failed, e.g. the allowance did not set the token
                aside for use and the user spent it before deposit was called.
                - The channel was closed/settled between the allowance call and
                the deposit call.
            AddressWithoutCode: The channel was settled during the deposit
                execution.
            DepositOverLimit: The total deposit amount is higher than the limit.
        """
        chain_state = views.state_from_raiden(self.raiden)

        token_addresses = views.get_token_identifiers(
            chain_state,
            registry_address,
        )
        channel_state = views.get_channelstate_for(
            chain_state=chain_state,
            payment_network_id=registry_address,
            token_address=token_address,
            partner_address=partner_address,
        )

        if not is_binary_address(token_address):
            raise InvalidAddress(
                'Expected binary address format for token in channel deposit')

        if not is_binary_address(partner_address):
            raise InvalidAddress(
                'Expected binary address format for partner in channel deposit'
            )

        if token_address not in token_addresses:
            raise UnknownTokenAddress('Unknown token address')

        if channel_state is None:
            raise InvalidAddress(
                'No channel with partner_address for the given token')

        if self.raiden.config['environment_type'] == Environment.PRODUCTION:
            per_token_network_deposit_limit = RED_EYES_PER_TOKEN_NETWORK_LIMIT
        else:
            per_token_network_deposit_limit = UINT256_MAX

        token = self.raiden.chain.token(token_address)
        token_network_registry = self.raiden.chain.token_network_registry(
            registry_address)
        token_network_address = token_network_registry.get_token_network(
            token_address)
        token_network_proxy = self.raiden.chain.token_network(
            token_network_address)
        channel_proxy = self.raiden.chain.payment_channel(
            canonical_identifier=channel_state.canonical_identifier, )

        if total_deposit == 0:
            raise DepositMismatch(
                'Attempted to deposit with total deposit being 0')

        addendum = total_deposit - channel_state.our_state.contract_balance

        total_network_balance = token.balance_of(registry_address)

        if total_network_balance + addendum > per_token_network_deposit_limit:
            raise DepositOverLimit(
                f'The deposit of {addendum} will exceed the '
                f'token network limit of {per_token_network_deposit_limit}', )

        balance = token.balance_of(self.raiden.address)

        functions = token_network_proxy.proxy.contract.functions
        deposit_limit = functions.channel_participant_deposit_limit().call()

        if total_deposit > deposit_limit:
            raise DepositOverLimit(
                f'The additional deposit of {addendum} will exceed the '
                f'channel participant limit of {deposit_limit}', )

        # If this check succeeds it does not imply the the `deposit` will
        # succeed, since the `deposit` transaction may race with another
        # transaction.
        if not balance >= addendum:
            msg = 'Not enough balance to deposit. {} Available={} Needed={}'.format(
                pex(token_address),
                balance,
                addendum,
            )
            raise InsufficientFunds(msg)

        # set_total_deposit calls approve
        # token.approve(netcontract_address, addendum)
        channel_proxy.set_total_deposit(
            total_deposit=total_deposit,
            block_identifier=views.state_from_raiden(self.raiden).block_hash,
        )

        target_address = self.raiden.address
        waiting.wait_for_participant_newbalance(
            raiden=self.raiden,
            payment_network_id=registry_address,
            token_address=token_address,
            partner_address=partner_address,
            target_address=target_address,
            target_balance=total_deposit,
            retry_timeout=retry_timeout,
        )
예제 #4
0
    def set_total_channel_deposit(
        self,
        registry_address: TokenNetworkRegistryAddress,
        token_address: TokenAddress,
        partner_address: Address,
        total_deposit: TokenAmount,
        retry_timeout: NetworkTimeout = DEFAULT_RETRY_TIMEOUT,
    ) -> None:
        """ Set the `total_deposit` in the channel with the peer at `partner_address` and the
        given `token_address` in order to be able to do transfers.

        Raises:
            InvalidBinaryAddress: If either token_address or partner_address is not
                20 bytes long.
            RaidenRecoverableError: May happen for multiple reasons:
                - If the token approval fails, e.g. the token may validate if
                account has enough balance for the allowance.
                - The deposit failed, e.g. the allowance did not set the token
                aside for use and the user spent it before deposit was called.
                - The channel was closed/settled between the allowance call and
                the deposit call.
            AddressWithoutCode: The channel was settled during the deposit
                execution.
            DepositOverLimit: The total deposit amount is higher than the limit.
            UnexpectedChannelState: The channel is no longer in an open state.
        """
        chain_state = views.state_from_raiden(self.raiden)

        token_addresses = views.get_token_identifiers(chain_state,
                                                      registry_address)
        channel_state = views.get_channelstate_for(
            chain_state=chain_state,
            token_network_registry_address=registry_address,
            token_address=token_address,
            partner_address=partner_address,
        )

        if not is_binary_address(token_address):
            raise InvalidBinaryAddress(
                "Expected binary address format for token in channel deposit")

        if not is_binary_address(partner_address):
            raise InvalidBinaryAddress(
                "Expected binary address format for partner in channel deposit"
            )

        if token_address not in token_addresses:
            raise UnknownTokenAddress("Unknown token address")

        if channel_state is None:
            raise NonexistingChannel(
                "No channel with partner_address for the given token")

        confirmed_block_identifier = chain_state.block_hash
        token = self.raiden.proxy_manager.token(
            token_address, block_identifier=confirmed_block_identifier)
        token_network_registry = self.raiden.proxy_manager.token_network_registry(
            registry_address, block_identifier=confirmed_block_identifier)
        token_network_address = token_network_registry.get_token_network(
            token_address=token_address,
            block_identifier=confirmed_block_identifier)

        if token_network_address is None:
            raise UnknownTokenAddress(
                f"Token {to_checksum_address(token_address)} is not registered "
                f"with the network {to_checksum_address(registry_address)}.")

        token_network_proxy = self.raiden.proxy_manager.token_network(
            address=token_network_address,
            block_identifier=confirmed_block_identifier)
        channel_proxy = self.raiden.proxy_manager.payment_channel(
            channel_state=channel_state,
            block_identifier=confirmed_block_identifier)

        blockhash = chain_state.block_hash
        token_network_proxy = channel_proxy.token_network

        safety_deprecation_switch = token_network_proxy.safety_deprecation_switch(
            block_identifier=blockhash)

        balance = token.balance_of(self.raiden.address,
                                   block_identifier=blockhash)

        network_balance = token.balance_of(
            address=Address(token_network_address), block_identifier=blockhash)
        token_network_deposit_limit = token_network_proxy.token_network_deposit_limit(
            block_identifier=blockhash)

        addendum = total_deposit - channel_state.our_state.contract_balance

        channel_participant_deposit_limit = token_network_proxy.channel_participant_deposit_limit(
            block_identifier=blockhash)
        total_channel_deposit = total_deposit + channel_state.partner_state.contract_balance

        is_channel_open = channel.get_status(
            channel_state) == ChannelState.STATE_OPENED

        if not is_channel_open:
            raise UnexpectedChannelState("Channel is not in an open state.")

        if safety_deprecation_switch:
            msg = ("This token_network has been deprecated. "
                   "All channels in this network should be closed and "
                   "the usage of the newly deployed token network contract "
                   "is highly encouraged.")
            raise TokenNetworkDeprecated(msg)

        if total_deposit <= channel_state.our_state.contract_balance:
            raise DepositMismatch("Total deposit did not increase.")

        # If this check succeeds it does not imply the `deposit` will
        # succeed, since the `deposit` transaction may race with another
        # transaction.
        if not (balance >= addendum):
            msg = "Not enough balance to deposit. {} Available={} Needed={}".format(
                to_checksum_address(token_address), balance, addendum)
            raise InsufficientFunds(msg)

        if network_balance + addendum > token_network_deposit_limit:
            msg = f"Deposit of {addendum} would have exceeded the token network deposit limit."
            raise DepositOverLimit(msg)

        if total_deposit > channel_participant_deposit_limit:
            msg = (f"Deposit of {total_deposit} is larger than the "
                   f"channel participant deposit limit")
            raise DepositOverLimit(msg)

        if total_channel_deposit >= UINT256_MAX:
            raise DepositOverLimit("Deposit overflow")

        try:
            channel_proxy.approve_and_set_total_deposit(
                total_deposit=total_deposit, block_identifier=blockhash)
        except RaidenRecoverableError as e:
            log.info(f"Deposit failed. {str(e)}")

        target_address = self.raiden.address
        waiting.wait_for_participant_deposit(
            raiden=self.raiden,
            token_network_registry_address=registry_address,
            token_address=token_address,
            partner_address=partner_address,
            target_address=target_address,
            target_balance=total_deposit,
            retry_timeout=retry_timeout,
        )