URI: 
       tlnpeer: - send data_loss_protect fields with channel_reestablish - close connection if we receive an unknown channel_reestablish - log all exceptions that make us close a connection - formatting - electrum - Electrum Bitcoin wallet
  HTML git clone https://git.parazyd.org/electrum
   DIR Log
   DIR Files
   DIR Refs
   DIR Submodules
       ---
   DIR commit 5eab60621db69d9adc237dccab0eefe91b620f0c
   DIR parent b76728d45970fc0fa58e2924792673947ff8aecc
  HTML Author: ThomasV <thomasv@electrum.org>
       Date:   Tue, 19 Mar 2019 12:58:09 +0100
       
       lnpeer:
        - send data_loss_protect fields with channel_reestablish
        - close connection if we receive an unknown channel_reestablish
        - log all exceptions that make us close a connection
        - formatting
       
       Diffstat:
         M electrum/lnpeer.py                  |      52 ++++++++++++++++++++-----------
       
       1 file changed, 33 insertions(+), 19 deletions(-)
       ---
   DIR diff --git a/electrum/lnpeer.py b/electrum/lnpeer.py
       t@@ -142,7 +142,8 @@ class Peer(PrintError):
        
            def on_accept_channel(self, payload):
                temp_chan_id = payload["temporary_channel_id"]
       -        if temp_chan_id not in self.channel_accepted: raise Exception("Got unknown accept_channel")
       +        if temp_chan_id not in self.channel_accepted:
       +            raise Exception("Got unknown accept_channel")
                self.channel_accepted[temp_chan_id].put_nowait(payload)
        
            def on_funding_signed(self, payload):
       t@@ -195,8 +196,8 @@ class Peer(PrintError):
                async def wrapper_func(self, *args, **kwargs):
                    try:
                        return await func(self, *args, **kwargs)
       -            except LightningPeerConnectionClosed as e:
       -                self.print_error("disconnecting gracefully. {}".format(e))
       +            except Exception as e:
       +                self.print_error("Disconnecting: {}".format(e))
                    finally:
                        self.close_and_cleanup()
                        self.lnworker.peers.pop(self.pubkey)
       t@@ -529,13 +530,21 @@ class Peer(PrintError):
        
            def on_channel_reestablish(self, payload):
                chan_id = payload["channel_id"]
       -        self.print_error("Received channel_reestablish", bh2u(chan_id))
       +        self.print_error("Received channel_reestablish", bh2u(chan_id), payload)
                chan = self.channels.get(chan_id)
                if not chan:
       -            self.print_error("Warning: received unknown channel_reestablish", bh2u(chan_id))
       -            return
       +            raise Exception('Unknown channel_reestablish ' + bh2u(chan_id))
                self.channel_reestablished[chan_id].set_result(payload)
        
       +    def try_to_get_remote_to_force_close_with_their_latest(chan_id):
       +        self.print_error("trying to get remote to force close", bh2u(chan_id))
       +        self.send_message(
       +            "channel_reestablish",
       +            channel_id=chan_id,
       +            next_local_commitment_number=0,
       +            next_remote_revocation_number=0
       +        )
       +
            @log_exceptions
            async def reestablish_channel(self, chan: Channel):
                await self.initialized.wait()
       t@@ -546,28 +555,33 @@ class Peer(PrintError):
                    return
                chan.set_state('REESTABLISHING')
                self.network.trigger_callback('channel', chan)
       -        self.send_message("channel_reestablish",
       +        # compute data_loss_protect fields
       +        current_remote_ctn = chan.config[REMOTE].ctn
       +        if current_remote_ctn == 0:
       +            last_rev_secret = 0
       +        else:
       +            revocation_store = chan.config[REMOTE].revocation_store
       +            last_rev_index = current_remote_ctn - 1
       +            last_rev_secret = revocation_store.retrieve_secret(RevocationStore.START_INDEX - last_rev_index)
       +        last_secret, last_point = chan.local_points(offset=-1)
       +        # send message
       +        self.send_message(
       +            "channel_reestablish",
                    channel_id=chan_id,
                    next_local_commitment_number=chan.config[LOCAL].ctn+1,
       -            next_remote_revocation_number=chan.config[REMOTE].ctn
       +            next_remote_revocation_number=current_remote_ctn,
       +            your_last_per_commitment_secret=last_rev_secret,
       +            my_current_per_commitment_point=last_point
                )
                channel_reestablish_msg = await self.channel_reestablished[chan_id]
                chan.set_state('OPENING')
       -
       -        def try_to_get_remote_to_force_close_with_their_latest():
       -            self.print_error("trying to get remote to force close", bh2u(chan_id))
       -            self.send_message("channel_reestablish",
       -                                      channel_id=chan_id,
       -                                      next_local_commitment_number=0,
       -                                      next_remote_revocation_number=0
       -                                      )
                # compare remote ctns
                their_next_local_ctn = int.from_bytes(channel_reestablish_msg["next_local_commitment_number"], 'big')
                their_next_remote_ctn = int.from_bytes(channel_reestablish_msg["next_remote_revocation_number"], 'big')
                if their_next_local_ctn != chan.config[REMOTE].ctn + 1:
                    self.print_error("expected remote ctn {}, got {}".format(chan.config[REMOTE].ctn + 1, their_next_local_ctn))
                    # TODO iff their ctn is lower than ours, we should force close instead
       -            try_to_get_remote_to_force_close_with_their_latest()
       +            self.try_to_get_remote_to_force_close_with_their_latest(chan_id)
                    return
                # compare local ctns
                if chan.config[LOCAL].ctn != their_next_remote_ctn:
       t@@ -588,7 +602,7 @@ class Peer(PrintError):
                    else:
                        self.print_error("expected local ctn {}, got {}".format(chan.config[LOCAL].ctn, their_next_remote_ctn))
                        # TODO iff their ctn is lower than ours, we should force close instead
       -                try_to_get_remote_to_force_close_with_their_latest()
       +                self.try_to_get_remote_to_force_close_with_their_latest(chan_id)
                        return
                # compare per commitment points (needs data_protect option)
                their_pcp = channel_reestablish_msg.get("my_current_per_commitment_point", None)
       t@@ -599,7 +613,7 @@ class Peer(PrintError):
                    if our_pcp != their_pcp:
                        self.print_error("Remote PCP mismatch: {} {}".format(bh2u(our_pcp), bh2u(their_pcp)))
                        # FIXME ...what now?
       -                try_to_get_remote_to_force_close_with_their_latest()
       +                self.try_to_get_remote_to_force_close_with_their_latest(chan_id)
                        return
                if their_next_local_ctn == chan.config[LOCAL].ctn+1 == 1 and chan.short_channel_id:
                    self.send_funding_locked(chan)