electrum

Electrum Bitcoin wallet
git clone https://git.parazyd.org/electrum
Log | Files | Refs | Submodules

commit a04e37d05019ecf77fabcd31d344efad60ef64b5
parent cf4f0c5d3a51cd6b42ea8cbeb09aaaa08a699aa5
Author: Janus <ysangkok@gmail.com>
Date:   Mon, 24 Sep 2018 18:10:14 +0200

keep htlc history in case a htlc fails

Diffstat:
Melectrum/lnbase.py | 4++--
Melectrum/lnhtlc.py | 22+++++++++++++++-------
2 files changed, 17 insertions(+), 9 deletions(-)

diff --git a/electrum/lnbase.py b/electrum/lnbase.py @@ -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() @@ -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) diff --git a/electrum/lnhtlc.py b/electrum/lnhtlc.py @@ -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"]) @@ -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 @@ -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 @@ -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 @@ -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): @@ -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)