URI: 
       tlnbase: handle some error codes re htlc failures ('UPDATE' flag) - electrum - Electrum Bitcoin wallet
  HTML git clone https://git.parazyd.org/electrum
   DIR Log
   DIR Files
   DIR Refs
   DIR Submodules
       ---
   DIR commit 8d4a5bd1d7d53015cfcfb96b0d3c8e8e8f7a0e9e
   DIR parent a8ace7ef4fa88a7977740f87d544cd8542a4fd3c
  HTML Author: SomberNight <somber.night@protonmail.com>
       Date:   Tue,  9 Oct 2018 21:48:17 +0200
       
       lnbase: handle some error codes re htlc failures ('UPDATE' flag)
       
       Diffstat:
         M electrum/lnbase.py                  |      58 ++++++++++++++++++++++++-------
       
       1 file changed, 45 insertions(+), 13 deletions(-)
       ---
   DIR diff --git a/electrum/lnbase.py b/electrum/lnbase.py
       t@@ -1014,7 +1014,6 @@ class Peer(PrintError):
            @aiosafe
            async def on_update_fail_htlc(self, payload):
                channel_id = payload["channel_id"]
       -        chan = self.channels[channel_id]
                htlc_id = int.from_bytes(payload["id"], "big")
                key = (channel_id, htlc_id)
                try:
       t@@ -1024,18 +1023,7 @@ class Peer(PrintError):
                    # attempted_route is not persisted, so we will get here then
                    self.print_error("UPDATE_FAIL_HTLC. cannot decode! attempted route is MISSING. {}".format(key))
                else:
       -            failure_msg, sender_idx = decode_onion_error(payload["reason"], [x.node_id for x in route], chan.onion_keys[htlc_id])
       -            code = OnionFailureCode(failure_msg.code)
       -            data = failure_msg.data
       -            self.print_error("UPDATE_FAIL_HTLC", repr(code), data)
       -            try:
       -                short_chan_id = route[sender_idx + 1].short_channel_id
       -            except IndexError:
       -                self.print_error("payment destination reported error")
       -            else:
       -                # TODO this should depend on the error
       -                # also, we need finer blacklisting (directed edges; nodes)
       -                self.network.path_finder.blacklist.add(short_chan_id)
       +            await self._handle_error_code_from_failed_htlc(payload["reason"], route, channel_id, htlc_id)
                # process update_fail_htlc on channel
                chan = self.channels[channel_id]
                chan.receive_fail_htlc(htlc_id)
       t@@ -1045,6 +1033,50 @@ class Peer(PrintError):
                await self.receive_revoke(chan)
                self.lnworker.save_channel(chan)
        
       +    async def _handle_error_code_from_failed_htlc(self, error_reason, route, channel_id, htlc_id):
       +        chan = self.channels[channel_id]
       +        failure_msg, sender_idx = decode_onion_error(error_reason,
       +                                                     [x.node_id for x in route],
       +                                                     chan.onion_keys[htlc_id])
       +        code = OnionFailureCode(failure_msg.code)
       +        data = failure_msg.data
       +        self.print_error("UPDATE_FAIL_HTLC", repr(code), data)
       +        # handle some specific error codes
       +        if code == OnionFailureCode.TEMPORARY_CHANNEL_FAILURE:
       +            channel_update = (258).to_bytes(length=2, byteorder="big") + data[2:]
       +            message_type, payload = decode_msg(channel_update)
       +            self.on_channel_update(payload)
       +        elif code == OnionFailureCode.AMOUNT_BELOW_MINIMUM:
       +            channel_update = (258).to_bytes(length=2, byteorder="big") + data[10:]
       +            message_type, payload = decode_msg(channel_update)
       +            self.on_channel_update(payload)
       +        elif code == OnionFailureCode.FEE_INSUFFICIENT:
       +            channel_update = (258).to_bytes(length=2, byteorder="big") + data[10:]
       +            message_type, payload = decode_msg(channel_update)
       +            self.on_channel_update(payload)
       +        elif code == OnionFailureCode.INCORRECT_CLTV_EXPIRY:
       +            channel_update = (258).to_bytes(length=2, byteorder="big") + data[6:]
       +            message_type, payload = decode_msg(channel_update)
       +            self.on_channel_update(payload)
       +        elif code == OnionFailureCode.EXPIRY_TOO_SOON:
       +            channel_update = (258).to_bytes(length=2, byteorder="big") + data[2:]
       +            message_type, payload = decode_msg(channel_update)
       +            self.on_channel_update(payload)
       +        elif code == OnionFailureCode.CHANNEL_DISABLED:
       +            channel_update = (258).to_bytes(length=2, byteorder="big") + data[4:]
       +            message_type, payload = decode_msg(channel_update)
       +            self.on_channel_update(payload)
       +        else:
       +            # blacklist channel after reporter node
       +            # TODO this should depend on the error (even more granularity)
       +            # also, we need finer blacklisting (directed edges; nodes)
       +            try:
       +                short_chan_id = route[sender_idx + 1].short_channel_id
       +            except IndexError:
       +                self.print_error("payment destination reported error")
       +            else:
       +                self.network.path_finder.blacklist.add(short_chan_id)
       +
            def send_commitment(self, chan):
                sig_64, htlc_sigs = chan.sign_next_commitment()
                self.send_message(gen_msg("commitment_signed", channel_id=chan.channel_id, signature=sig_64, num_htlcs=len(htlc_sigs), htlc_signature=b"".join(htlc_sigs)))