URI: 
       tlnchannel.available_to_spend: consider both receiver's and sender's ctx - electrum - Electrum Bitcoin wallet
  HTML git clone https://git.parazyd.org/electrum
   DIR Log
   DIR Files
   DIR Refs
   DIR Submodules
       ---
   DIR commit 7fccd4fc5e0044d35b4cf717b1fc0137b6321b0e
   DIR parent 817411b889fa57ea8205ed4abea1cc08aa2d666a
  HTML Author: SomberNight <somber.night@protonmail.com>
       Date:   Wed, 10 Jun 2020 20:23:12 +0200
       
       lnchannel.available_to_spend: consider both receiver's and sender's ctx
       
       Diffstat:
         M electrum/lnchannel.py               |      85 ++++++++++++++-----------------
       
       1 file changed, 38 insertions(+), 47 deletions(-)
       ---
   DIR diff --git a/electrum/lnchannel.py b/electrum/lnchannel.py
       t@@ -1054,53 +1054,44 @@ class Channel(AbstractChannel):
                assert type(subject) is HTLCOwner
                sender = subject
                receiver = subject.inverted()
       -        ctx_owner = receiver
       -        # TODO but what about the other ctx? BOLT-02 only talks about checking the receiver's ctx,
       -        #      however the channel reserve is only meaningful if we also check the sender's ctx!
       -        #      in particular, note that dust limits can be different between the parties!
       -        #      but due to the racy nature of this, we cannot be sure exactly what the sender's
       -        #      next ctx will look like (e.g. what feerate it will use). hmmm :/
       -        ctn = self.get_next_ctn(ctx_owner)
       -        sender_balance_msat = self.balance_minus_outgoing_htlcs(whose=sender, ctx_owner=ctx_owner, ctn=ctn)
       -        receiver_balance_msat = self.balance_minus_outgoing_htlcs(whose=receiver, ctx_owner=ctx_owner, ctn=ctn)
       -        sender_reserve_msat = self.config[receiver].reserve_sat * 1000
       -        receiver_reserve_msat = self.config[sender].reserve_sat * 1000
       -        initiator = LOCAL if self.constraints.is_initiator else REMOTE
       -        # the initiator/funder pays on-chain fees
       -        num_htlcs_in_ctx = len(self.included_htlcs(ctx_owner, SENT, ctn=ctn) + self.included_htlcs(ctx_owner, RECEIVED, ctn=ctn))
       -        feerate = self.get_feerate(ctx_owner, ctn=ctn)
       -        ctx_fees_msat = calc_fees_for_commitment_tx(
       -            num_htlcs=num_htlcs_in_ctx,
       -            feerate=feerate,
       -            is_local_initiator=self.constraints.is_initiator,
       -            round_to_sat=False,
       -        )
       -        # note: if this supposed new HTLC is large enough to create an output, the initiator needs to pay for that too
       -        # note: if sender != initiator, both the sender and the receiver need to "afford" the payment
       -        htlc_fee_msat = fee_for_htlc_output(feerate=feerate)
       -        # TODO stuck channels. extra funder reserve? "fee spike buffer" (maybe only if "strict")
       -        #      see https://github.com/lightningnetwork/lightning-rfc/issues/728
       -        # note: in terms of on-chain outputs, as we are considering the htlc_receiver's ctx, this is a "received" HTLC
       -        htlc_trim_threshold_msat = received_htlc_trim_threshold_sat(dust_limit_sat=self.config[receiver].dust_limit_sat, feerate=feerate) * 1000
       -        if strict:
       -            # also consider the other ctx, where the trim threshold is different
       -            # note: the 'feerate' we use is not technically correct but we have no way
       -            #       of knowing the actual future feerate ahead of time (this is a protocol bug)
       -            htlc_trim_threshold_msat = min(htlc_trim_threshold_msat,
       -                                           offered_htlc_trim_threshold_sat(dust_limit_sat=self.config[sender].dust_limit_sat, feerate=feerate) * 1000)
       -        max_send_msat = sender_balance_msat - sender_reserve_msat - ctx_fees_msat[sender]
       -        if max_send_msat < htlc_trim_threshold_msat:
       -            # there will be no corresponding HTLC output
       -            return max_send_msat
       -        if sender == initiator:
       -            max_send_after_htlc_fee_msat = max_send_msat - htlc_fee_msat
       -            max_send_msat = max(htlc_trim_threshold_msat - 1, max_send_after_htlc_fee_msat)
       -            return max_send_msat
       -        else:
       -            # the receiver is the initiator, so they need to be able to pay tx fees
       -            if receiver_balance_msat - receiver_reserve_msat - ctx_fees_msat[receiver] - htlc_fee_msat < 0:
       -                max_send_msat = htlc_trim_threshold_msat - 1
       -            return max_send_msat
       +        initiator = LOCAL if self.constraints.is_initiator else REMOTE  # the initiator/funder pays on-chain fees
       +
       +        def consider_ctx(*, ctx_owner: HTLCOwner) -> int:
       +            ctn = self.get_next_ctn(ctx_owner)
       +            sender_balance_msat = self.balance_minus_outgoing_htlcs(whose=sender, ctx_owner=ctx_owner, ctn=ctn)
       +            receiver_balance_msat = self.balance_minus_outgoing_htlcs(whose=receiver, ctx_owner=ctx_owner, ctn=ctn)
       +            sender_reserve_msat = self.config[receiver].reserve_sat * 1000
       +            receiver_reserve_msat = self.config[sender].reserve_sat * 1000
       +            num_htlcs_in_ctx = len(self.included_htlcs(ctx_owner, SENT, ctn=ctn) + self.included_htlcs(ctx_owner, RECEIVED, ctn=ctn))
       +            feerate = self.get_feerate(ctx_owner, ctn=ctn)
       +            ctx_fees_msat = calc_fees_for_commitment_tx(
       +                num_htlcs=num_htlcs_in_ctx,
       +                feerate=feerate,
       +                is_local_initiator=self.constraints.is_initiator,
       +                round_to_sat=False,
       +            )
       +            htlc_fee_msat = fee_for_htlc_output(feerate=feerate)
       +            htlc_trim_func = received_htlc_trim_threshold_sat if ctx_owner == receiver else offered_htlc_trim_threshold_sat
       +            htlc_trim_threshold_msat = htlc_trim_func(dust_limit_sat=self.config[ctx_owner].dust_limit_sat, feerate=feerate) * 1000
       +            max_send_msat = sender_balance_msat - sender_reserve_msat - ctx_fees_msat[sender]
       +            if max_send_msat < htlc_trim_threshold_msat:
       +                # there will be no corresponding HTLC output
       +                return max_send_msat
       +            if sender == initiator:
       +                max_send_after_htlc_fee_msat = max_send_msat - htlc_fee_msat
       +                max_send_msat = max(htlc_trim_threshold_msat - 1, max_send_after_htlc_fee_msat)
       +                return max_send_msat
       +            else:
       +                # the receiver is the initiator, so they need to be able to pay tx fees
       +                if receiver_balance_msat - receiver_reserve_msat - ctx_fees_msat[receiver] - htlc_fee_msat < 0:
       +                    max_send_msat = htlc_trim_threshold_msat - 1
       +                return max_send_msat
       +
       +        max_send_msat = min(consider_ctx(ctx_owner=receiver),
       +                            consider_ctx(ctx_owner=sender))
       +        max_send_msat = max(max_send_msat, 0)
       +        return max_send_msat
       +
        
            def included_htlcs(self, subject: HTLCOwner, direction: Direction, ctn: int = None) -> Sequence[UpdateAddHtlc]:
                """Returns list of non-dust HTLCs for subject's commitment tx at ctn,