def set_total_deposit(
            self,
            given_block_identifier: BlockSpecification,
            channel_identifier: ChannelID,
            total_deposit: TokenAmount,
            partner: Address,
    ):
        """ Set channel's total deposit.

        `total_deposit` has to be monotonically increasing, this is enforced by
        the `TokenNetwork` smart contract. This is done for the same reason why
        the balance proofs have a monotonically increasing transferred amount,
        it simplifies the analysis of bad behavior and the handling code of
        out-dated balance proofs.

        Races to `set_total_deposit` are handled by the smart contract, where
        largest total deposit wins. The end balance of the funding accounts is
        undefined. E.g.

        - Acc1 calls set_total_deposit with 10 tokens
        - Acc2 calls set_total_deposit with 13 tokens

        - If Acc2's transaction is mined first, then Acc1 token supply is left intact.
        - If Acc1's transaction is mined first, then Acc2 will only move 3 tokens.

        Races for the same account don't have any unexpeted side-effect.

        Raises:
            DepositMismatch: If the new request total deposit is lower than the
                existing total deposit on-chain for the `given_block_identifier`.
            RaidenRecoverableError: If the channel was closed meanwhile the
                deposit was in transit.
            RaidenUnrecoverableError: If the transaction was sucessful and the
                deposit_amount is not as large as the requested value.
            RuntimeError: If the token address is empty.
            ValueError: If an argument is of the invalid type.
        """
        if not isinstance(total_deposit, int):
            raise ValueError('total_deposit needs to be an integer number.')
        token_address = self.token_address()
        token = Token(
            jsonrpc_client=self.client,
            token_address=token_address,
            contract_manager=self.contract_manager,
        )
        checking_block = self.client.get_checking_block()
        error_prefix = 'setTotalDeposit call will fail'
        with self.channel_operations_lock[partner], self.deposit_lock:
            previous_total_deposit = self._detail_participant(
                channel_identifier=channel_identifier,
                participant=self.node_address,
                partner=partner,
                block_identifier=given_block_identifier,
            ).deposit
            amount_to_deposit = TokenAmount(total_deposit - previous_total_deposit)
            log_details = {
                'token_network': pex(self.address),
                'channel_identifier': channel_identifier,
                'node': pex(self.node_address),
                'partner': pex(partner),
                'new_total_deposit': total_deposit,
                'previous_total_deposit': previous_total_deposit,
            }
            try:
                self._deposit_preconditions(
                    channel_identifier=channel_identifier,
                    total_deposit=total_deposit,
                    partner=partner,
                    token=token,
                    previous_total_deposit=previous_total_deposit,
                    log_details=log_details,
                    block_identifier=given_block_identifier,
                )
            except NoStateForBlockIdentifier:
                # If preconditions end up being on pruned state skip them. Estimate
                # gas will stop us from sending a transaction that will fail
                pass

            # If there are channels being set up concurrenlty either the
            # allowance must be accumulated *or* the calls to `approve` and
            # `setTotalDeposit` must be serialized. This is necessary otherwise
            # the deposit will fail.
            #
            # Calls to approve and setTotalDeposit are serialized with the
            # deposit_lock to avoid transaction failure, because with two
            # concurrent deposits, we may have the transactions executed in the
            # following order
            #
            # - approve
            # - approve
            # - setTotalDeposit
            # - setTotalDeposit
            #
            # in which case  the second `approve` will overwrite the first,
            # and the first `setTotalDeposit` will consume the allowance,
            #  making the second deposit fail.
            token.approve(
                allowed_address=Address(self.address),
                allowance=amount_to_deposit,
            )

            gas_limit = self.proxy.estimate_gas(
                checking_block,
                'setTotalDeposit',
                channel_identifier=channel_identifier,
                participant=self.node_address,
                total_deposit=total_deposit,
                partner=partner,
            )

            if gas_limit:
                gas_limit = safe_gas_limit(gas_limit, GAS_REQUIRED_FOR_SET_TOTAL_DEPOSIT)
                error_prefix = 'setTotalDeposit call failed'

                log.debug('setTotalDeposit called', **log_details)
                transaction_hash = self.proxy.transact(
                    'setTotalDeposit',
                    gas_limit,
                    channel_identifier=channel_identifier,
                    participant=self.node_address,
                    total_deposit=total_deposit,
                    partner=partner,
                )
                self.client.poll(transaction_hash)
                receipt_or_none = check_transaction_threw(self.client, transaction_hash)

            transaction_executed = gas_limit is not None
            if not transaction_executed or receipt_or_none:
                if transaction_executed:
                    block = receipt_or_none['blockNumber']
                else:
                    block = checking_block

                self.proxy.jsonrpc_client.check_for_insufficient_eth(
                    transaction_name='setTotalDeposit',
                    transaction_executed=transaction_executed,
                    required_gas=GAS_REQUIRED_FOR_SET_TOTAL_DEPOSIT,
                    block_identifier=block,
                )
                error_type, msg = self._check_why_deposit_failed(
                    channel_identifier=channel_identifier,
                    partner=partner,
                    token=token,
                    amount_to_deposit=amount_to_deposit,
                    total_deposit=total_deposit,
                    transaction_executed=transaction_executed,
                    block_identifier=block,
                )

                error_msg = f'{error_prefix}. {msg}'
                if error_type == RaidenRecoverableError:
                    log.warning(error_msg, **log_details)
                else:
                    log.critical(error_msg, **log_details)
                raise error_type(error_msg)

            log.info('setTotalDeposit successful', **log_details)
Set channel's total deposit.

        `total_deposit` has to be monotonically increasing, this is enforced by
        the `TokenNetwork` smart contract. This is done for the same reason why
        the balance proofs have a monotonically increasing transferred amount,
        it simplifies the analysis of bad behavior and the handling code of
        out-dated balance proofs.

        Races to `set_total_deposit` are handled by the smart contract, where
        largest total deposit wins. The end balance of the funding accounts is
        undefined. E.g.

        - Acc1 calls set_total_deposit with 10 tokens
        - Acc2 calls set_total_deposit with 13 tokens

        - If Acc2's transaction is mined first, then Acc1 token supply is left intact.
        - If Acc1's transaction is mined first, then Acc2 will only move 3 tokens.

        Races for the same account don't have any unexpeted side-effect.

        Raises:
            DepositMismatch: If the new request total deposit is lower than the
                existing total deposit on-chain for the `given_block_identifier`.
            RaidenRecoverableError: If the channel was closed meanwhile the
                deposit was in transit.
            RaidenUnrecoverableError: If the transaction was sucessful and the
                deposit_amount is not as large as the requested value.
            RuntimeError: If the token address is empty.
            ValueError: If an argument is of the invalid type.