URI: 
       tlnchan.receive_revocation: tolerate not having htlc fail reason - electrum - Electrum Bitcoin wallet
  HTML git clone https://git.parazyd.org/electrum
   DIR Log
   DIR Files
   DIR Refs
   DIR Submodules
       ---
   DIR commit ee24c74f192960f3e2d31ffb6b910e6bfb6bd90f
   DIR parent 7110fde25d1f6c4cc6420a226f504dcc1a32cbca
  HTML Author: SomberNight <somber.night@protonmail.com>
       Date:   Fri, 23 Oct 2020 02:35:20 +0200
       
       lnchan.receive_revocation: tolerate not having htlc fail reason
       
       If we get a revack after reestablish, but the fail_htlc was already
       committed in a previous app-session, the fail_htlc will not be re-sent and
       we will not have the reason (as it's not persisted).
       
       fixes #6675
       
       Diffstat:
         M electrum/lnchannel.py               |      12 ++++++++++--
         M electrum/lnworker.py                |      10 ++++++++--
       
       2 files changed, 18 insertions(+), 4 deletions(-)
       ---
   DIR diff --git a/electrum/lnchannel.py b/electrum/lnchannel.py
       t@@ -997,14 +997,22 @@ class Channel(AbstractChannel):
                        self.lnworker.payment_sent(self, htlc.payment_hash)
                    failed = self.hm.failed_in_ctn(new_ctn)
                    for htlc in failed:
       -                error_bytes, failure_message = self._receive_fail_reasons.pop(htlc.htlc_id)
       +                try:
       +                    error_bytes, failure_message = self._receive_fail_reasons.pop(htlc.htlc_id)
       +                except KeyError:
       +                    error_bytes, failure_message = None, None
                        # if we are forwarding, save error message to disk
                        if self.lnworker.get_payment_info(htlc.payment_hash) is None:
                            self.save_fail_htlc_reason(htlc.htlc_id, error_bytes, failure_message)
                        else:
                            self.lnworker.payment_failed(self, htlc.payment_hash, error_bytes, failure_message)
        
       -    def save_fail_htlc_reason(self, htlc_id, error_bytes, failure_message):
       +    def save_fail_htlc_reason(
       +            self,
       +            htlc_id: int,
       +            error_bytes: Optional[bytes],
       +            failure_message: Optional['OnionRoutingFailureMessage'],
       +    ):
                error_hex = error_bytes.hex() if error_bytes else None
                failure_hex = failure_message.to_bytes().hex() if failure_message else None
                self.hm.log['fail_htlc_reasons'][htlc_id] = (error_hex, failure_hex)
   DIR diff --git a/electrum/lnworker.py b/electrum/lnworker.py
       t@@ -59,7 +59,7 @@ from .lnutil import (Outpoint, LNPeerAddr,
                             BarePaymentAttemptLog, derive_payment_secret_from_payment_preimage)
        from .lnutil import ln_dummy_address, ln_compare_features, IncompatibleLightningFeatures
        from .transaction import PartialTxOutput, PartialTransaction, PartialTxInput
       -from .lnonion import OnionFailureCode, process_onion_packet, OnionPacket
       +from .lnonion import OnionFailureCode, process_onion_packet, OnionPacket, OnionRoutingFailureMessage
        from .lnmsg import decode_msg
        from .i18n import _
        from .lnrouter import (RouteEdge, LNPaymentRoute, LNPaymentPath, is_route_sane_to_use,
       t@@ -1241,7 +1241,13 @@ class LNWallet(LNWorker):
                info = info._replace(status=status)
                self.save_payment_info(info)
        
       -    def payment_failed(self, chan, payment_hash: bytes, error_bytes: bytes, failure_message):
       +    def payment_failed(
       +            self,
       +            chan: Channel,
       +            payment_hash: bytes,
       +            error_bytes: Optional[bytes],
       +            failure_message: Optional['OnionRoutingFailureMessage'],
       +    ):
                self.set_payment_status(payment_hash, PR_UNPAID)
                f = self.pending_payments.get(payment_hash)
                if f and not f.cancelled():