electrum

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

commit fed6c96693c8a8ce31bed310eff19d43a86f1384
parent 3c0df28c98a275e9eafac409d383dc383c1c5065
Author: ThomasV <thomasv@electrum.org>
Date:   Sun, 19 May 2019 13:24:29 +0200

add option to remove channel after it has been closed

Diffstat:
Melectrum/gui/qt/channels_list.py | 54+++++++++++++++++++++++++++++++++---------------------
Melectrum/lnworker.py | 23++++++++++++++++++-----
2 files changed, 51 insertions(+), 26 deletions(-)

diff --git a/electrum/gui/qt/channels_list.py b/electrum/gui/qt/channels_list.py @@ -23,6 +23,8 @@ class ChannelsList(MyTreeView): self.main_window = parent self.update_rows.connect(self.do_update_rows) self.update_single_row.connect(self.do_update_single_row) + self.network = self.parent.network + self.lnworker = self.parent.wallet.lnworker def format_fields(self, chan): labels = {} @@ -42,36 +44,46 @@ class ChannelsList(MyTreeView): chan.get_state() ] + def on_success(txid): + self.main_window.show_error('Channel closed' + '\n' + txid) + + def on_failure(exc_info): + type_, e, tb = exc_info + traceback.print_tb(tb) + self.main_window.show_error('Failed to close channel:\n{}'.format(repr(e))) + + def close(self, channel_id): + def task(): + coro = self.lnworker.close_channel(channel_id) + return self.network.run_from_another_thread(coro) + WaitingDialog(self, 'please wait..', task, self.on_success, self.on_failure) + + def force_close(self, channel_id): + def task(): + coro = self.lnworker.force_close_channel(channel_id) + return self.network.run_from_another_thread(coro) + if self.parent.question('Force-close channel?\nReclaimed funds will not be immediately available.'): + WaitingDialog(self, 'please wait..', task, self.on_success, self.on_failure) + + def remove_channel(self, channel_id): + if self.main_window.question(_('Are you sure you want to delete this channel? This will purge associated transactions from your wallet history.')): + self.lnworker.remove_channel(channel_id) + def create_menu(self, position): from .util import WaitingDialog - network = self.parent.network - lnworker = self.parent.wallet.lnworker menu = QMenu() idx = self.selectionModel().currentIndex() item = self.model().itemFromIndex(idx) if not item: return channel_id = idx.sibling(idx.row(), 0).data(QtCore.Qt.UserRole) - def on_success(txid): - self.main_window.show_error('Channel closed' + '\n' + txid) - def on_failure(exc_info): - type_, e, tb = exc_info - traceback.print_tb(tb) - self.main_window.show_error('Failed to close channel:\n{}'.format(repr(e))) - def close(): - def task(): - coro = lnworker.close_channel(channel_id) - return network.run_from_another_thread(coro) - WaitingDialog(self, 'please wait..', task, on_success, on_failure) - def force_close(): - def task(): - coro = lnworker.force_close_channel(channel_id) - return network.run_from_another_thread(coro) - if self.parent.question('Force-close channel?\nClaiming funds will not be immediately available.'): - WaitingDialog(self, 'please wait..', task, on_success, on_failure) + chan = self.lnworker.channels[channel_id] menu.addAction(_("Details..."), lambda: self.details(channel_id)) - menu.addAction(_("Close channel"), close) - menu.addAction(_("Force-close channel"), force_close) + if not chan.is_closed(): + menu.addAction(_("Close channel"), lambda: self.close_channel(channel_id)) + menu.addAction(_("Force-close channel"), lambda: self.force_close(channel_id)) + else: + menu.addAction(_("Remove"), lambda: self.remove_channel(channel_id)) menu.exec_(self.viewport().mapToGlobal(position)) def details(self, channel_id): diff --git a/electrum/lnworker.py b/electrum/lnworker.py @@ -443,16 +443,20 @@ class LNWallet(LNWorker): with self.lock: return {x: y for (x, y) in self.channels.items() if y.node_id == node_id} - def save_channel(self, openchannel): - assert type(openchannel) is Channel - if openchannel.config[REMOTE].next_per_commitment_point == openchannel.config[REMOTE].current_per_commitment_point: + def save_channel(self, chan): + assert type(chan) is Channel + if chan.config[REMOTE].next_per_commitment_point == chan.config[REMOTE].current_per_commitment_point: raise Exception("Tried to save channel with next_point == current_point, this should not happen") with self.lock: - self.channels[openchannel.channel_id] = openchannel + self.channels[chan.channel_id] = chan + self.save_channels() + self.network.trigger_callback('channel', chan) + + def save_channels(self): + with self.lock: dumped = [x.serialize() for x in self.channels.values()] self.storage.put("channels", dumped) self.storage.write() - self.network.trigger_callback('channel', openchannel) def save_short_chan_id(self, chan): """ @@ -875,6 +879,15 @@ class LNWallet(LNWorker): await self.network.broadcast_transaction(tx) return tx.txid() + def remove_channel(self, chan_id): + # TODO: assert that closing tx is deep-mined and htlcs are swept + chan = self.channels[chan_id] + assert chan.is_closed() + self.channels.pop(chan_id) + self.save_channel(chan) + self.network.trigger_callback('channels') + self.network.trigger_callback('wallet_updated') + async def reestablish_peers_and_channels(self): async def reestablish_peer_for_given_channel(): # try last good address first