URI: 
       tkeep htlc history in case a htlc fails - electrum - Electrum Bitcoin wallet
  HTML git clone https://git.parazyd.org/electrum
   DIR Log
   DIR Files
   DIR Refs
   DIR Submodules
       ---
   DIR commit a04e37d05019ecf77fabcd31d344efad60ef64b5
   DIR parent cf4f0c5d3a51cd6b42ea8cbeb09aaaa08a699aa5
  HTML Author: Janus <ysangkok@gmail.com>
       Date:   Mon, 24 Sep 2018 18:10:14 +0200
       
       keep htlc history in case a htlc fails
       
       Diffstat:
         M electrum/lnbase.py                  |       4 ++--
         M electrum/lnhtlc.py                  |      22 +++++++++++++++-------
       
       2 files changed, 17 insertions(+), 9 deletions(-)
       ---
   DIR diff --git a/electrum/lnbase.py b/electrum/lnbase.py
       t@@ -885,7 +885,7 @@ class Peer(PrintError):
                    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)))
                    await self.receive_revoke(chan)
       -            chan.fail_htlc(htlc)
       +            chan.receive_fail_htlc(htlc_id)
                    await self.receive_commitment(chan)
                    self.revoke(chan)
                    sig_64, htlc_sigs = chan.sign_next_commitment()
       t@@ -1082,7 +1082,7 @@ class Peer(PrintError):
                if chan_id not in self.closing_signed: raise Exception("Got unknown closing_signed")
                self.closing_signed[chan_id].put_nowait(payload)
        
       -    async def on_shutdown(self, payload):
       +    def on_shutdown(self, payload):
                coro = self.shutdown_coroutine(payload)
                asyncio.run_coroutine_threadsafe(coro, self.network.asyncio_loop)
        
   DIR diff --git a/electrum/lnhtlc.py b/electrum/lnhtlc.py
       t@@ -20,6 +20,7 @@ from .lnutil import funding_output_script, LOCAL, REMOTE, HTLCOwner, make_closin
        from .transaction import Transaction
        
        
       +FailHtlc = namedtuple("FailHtlc", ["htlc_id"])
        SettleHtlc = namedtuple("SettleHtlc", ["htlc_id"])
        RevokeAndAck = namedtuple("RevokeAndAck", ["per_commitment_secret", "next_per_commitment_point"])
        
       t@@ -172,6 +173,8 @@ class HTLCStateMachine(PrintError):
                            self.log[subject].append(UpdateAddHtlc(*decodeAll(y)))
                        elif typ == "SettleHtlc":
                            self.log[subject].append(SettleHtlc(*decodeAll(y)))
       +                elif typ == "FailHtlc":
       +                    self.log[subject].append(FailHtlc(*decodeAll(y)))
                        else:
                            assert False
        
       t@@ -247,7 +250,8 @@ class HTLCStateMachine(PrintError):
                """
                for htlc in self.log[LOCAL]:
                    if not type(htlc) is UpdateAddHtlc: continue
       -            if htlc.locked_in[LOCAL] is None: htlc.locked_in[LOCAL] = self.local_state.ctn
       +            if htlc.locked_in[LOCAL] is None and FailHtlc(htlc.htlc_id) not in self.log[REMOTE]:
       +                htlc.locked_in[LOCAL] = self.local_state.ctn
                self.print_error("sign_next_commitment")
        
                pending_remote_commitment = self.pending_remote_commitment
       t@@ -305,7 +309,8 @@ class HTLCStateMachine(PrintError):
                self.print_error("receive_new_commitment")
                for htlc in self.log[REMOTE]:
                    if not type(htlc) is UpdateAddHtlc: continue
       -            if htlc.locked_in[REMOTE] is None: htlc.locked_in[REMOTE] = self.remote_state.ctn
       +            if htlc.locked_in[REMOTE] is None and FailHtlc(htlc.htlc_id) not in self.log[LOCAL]:
       +                htlc.locked_in[REMOTE] = self.remote_state.ctn
                assert len(htlc_sigs) == 0 or type(htlc_sigs[0]) is bytes
        
                pending_local_commitment = self.pending_local_commitment
       t@@ -642,11 +647,12 @@ class HTLCStateMachine(PrintError):
                assert len([x for x in self.log[LOCAL] if x.htlc_id == htlc_index and type(x) is UpdateAddHtlc]) == 1, (self.log[LOCAL], htlc_index)
                self.log[REMOTE].append(SettleHtlc(htlc_index))
        
       -    def fail_htlc(self, htlc):
       -        # TODO
       -        self.log[LOCAL] = []
       -        self.log[REMOTE] = []
       -        self.print_error("fail_htlc (EMPTIED LOGS)")
       +    def receive_fail_htlc(self, htlc_id):
       +        self.print_error("receive_fail_htlc")
       +        htlc = self.lookup_htlc(self.log[LOCAL], htlc_id)
       +        htlc.locked_in[LOCAL] = None
       +        htlc.locked_in[REMOTE] = None
       +        self.log[REMOTE].append(FailHtlc(htlc_id))
        
            @property
            def current_height(self):
       t@@ -696,6 +702,8 @@ class HTLCStateMachine(PrintError):
                            return o.serialize()
                        if isinstance(o, SettleHtlc):
                            return json.dumps(('SettleHtlc', namedtuples_to_dict(o)))
       +                if isinstance(o, FailHtlc):
       +                    return json.dumps(('FailHtlc', namedtuples_to_dict(o)))
                        if isinstance(o, UpdateAddHtlc):
                            return json.dumps(('UpdateAddHtlc', namedtuples_to_dict(o)))
                        return super(MyJsonEncoder, self)