electrum

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

commit 4d32478f301bf732b88c0a4be9200d9f26792ca7
parent 1946254ef2627303396b61a413383d5ce5362cc3
Author: SomberNight <somber.night@protonmail.com>
Date:   Tue,  9 Oct 2018 17:41:24 +0200

on_channel_reestablish: try to get remote to force close channel if out-of-sync.

see ACINQ/eclair#727 and lightningnetwork/lnd#1904

Diffstat:
Melectrum/lnbase.py | 41++++++++++++++++++++++++++++++-----------
1 file changed, 30 insertions(+), 11 deletions(-)

diff --git a/electrum/lnbase.py b/electrum/lnbase.py @@ -792,23 +792,42 @@ class Peer(PrintError): if not chan: print("Warning: received unknown channel_reestablish", bh2u(chan_id)) return + + 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(gen_msg("channel_reestablish", + channel_id=chan_id, + next_local_commitment_number=0, + next_remote_revocation_number=0 + )) + channel_reestablish_msg = payload + # compare remote ctns remote_ctn = int.from_bytes(channel_reestablish_msg["next_local_commitment_number"], 'big') if remote_ctn != chan.remote_state.ctn + 1: - raise Exception("expected remote ctn {}, got {}".format(chan.remote_state.ctn + 1, remote_ctn)) + self.print_error("expected remote ctn {}, got {}".format(chan.remote_state.ctn + 1, 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() + return + # compare local ctns local_ctn = int.from_bytes(channel_reestablish_msg["next_remote_revocation_number"], 'big') if local_ctn != chan.local_state.ctn: - raise Exception("expected local ctn {}, got {}".format(chan.local_state.ctn, local_ctn)) - try: - their = channel_reestablish_msg["my_current_per_commitment_point"] - except KeyError: # no data_protect option - self.channel_reestablished[chan_id].set_result(True) + self.print_error("expected local ctn {}, got {}".format(chan.local_state.ctn, 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() return - our = chan.remote_state.current_per_commitment_point - if our is None: - our = chan.remote_state.next_per_commitment_point - if our != their: - raise Exception("Remote PCP mismatch: {} {}".format(bh2u(our), bh2u(their))) + # compare per commitment points (needs data_protect option) + their_pcp = channel_reestablish_msg.get("my_current_per_commitment_point", None) + if their_pcp is not None: + our_pcp = chan.remote_state.current_per_commitment_point + if our_pcp is None: + our_pcp = chan.remote_state.next_per_commitment_point + 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() + return + # checks done self.channel_reestablished[chan_id].set_result(True) def funding_locked(self, chan):