Browse Source

improve watchtower gui

dependabot/pip/contrib/deterministic-build/ecdsa-0.13.3
ThomasV 6 years ago
parent
commit
8aa4ce0704
  1. 67
      electrum/gui/qt/watchtower_window.py
  2. 10
      electrum/lnwatcher.py

67
electrum/gui/qt/watchtower_window.py

@ -33,42 +33,67 @@ import PyQt5.QtCore as QtCore
from electrum.i18n import _ from electrum.i18n import _
from .util import * from .util import *
help_wt = _("""A watchtower is a process that monitors your channels while you are offline, and prevents the other party from stealing funds in the channel.""") help_about = _("""The local watchtower will persist on this computer after you close
help_local = _("""Electrum runs a watchtower on your computer. This process will persist after you close your wallet. It will not persist if you exit Electrum from the tray menu""") your wallet, but it requires to be online regularly.""")
help_remote = _("""To run a remote watchtower, start an electrum daemon on a computer that is always connected to the Internet, and set 'watchtower_host' and 'watchtower_port' in its config""")
help_remote = _(""" To setup a remote watchtower, configure a remote electrum daemon
with 'watchtower_host' and 'watchtower_port' """)
class WatcherList(MyTreeView):
def __init__(self, parent):
super().__init__(parent, self.create_menu, stretch_column=0, editable_columns=[])
self.setModel(QStandardItemModel(self))
self.setSortingEnabled(True)
self.update()
def create_menu(self, x):
pass
def update(self):
self.model().clear()
self.update_headers({0:_('Outpoint'), 1:_('Tx'), 2:_('Status')})
for outpoint, sweep_dict in self.parent.lnwatcher.sweepstore.items():
status = self.parent.lnwatcher.get_channel_status(outpoint)
items = [QStandardItem(e) for e in [outpoint, "%d"%len(sweep_dict), status]]
self.model().insertRow(self.model().rowCount(), items)
class WatchTowerWindow(QDialog): class WatchTowerWindow(QDialog):
def __init__(self, gui_object): def __init__(self, gui_object):
QDialog.__init__(self) QDialog.__init__(self)
self.gui_object = gui_object self.gui_object = gui_object
self.lnwatcher = gui_object.daemon.network.lnwatcher
self.wallet = self.lnwatcher
self.config = gui_object.config self.config = gui_object.config
self.lnwatcher = gui_object.daemon.network.lnwatcher
self.setWindowTitle(_('Watchtower')) self.setWindowTitle(_('Watchtower'))
self.setMinimumSize(600, 20) self.setMinimumSize(600, 20)
vbox = QVBoxLayout(self)
watchtower_url = self.config.get('watchtower_url') watchtower_url = self.config.get('watchtower_url')
self.watchtower_e = QLineEdit(watchtower_url) self.watchtower_e = QLineEdit(watchtower_url)
self.channel_list = QTreeWidget(self) self.channel_list = WatcherList(self)
self.channel_list.setHeaderLabels([_('Node ID'), _('Amount')]) # local
local_w = QWidget()
vbox.addWidget(WWLabel(help_wt)) vbox_local = QVBoxLayout(local_w)
vbox.addStretch(1) vbox_local.addWidget(WWLabel(help_about))
vbox.addWidget(HelpLabel(_('Local Watchtower') + ':', help_local)) vbox_local.addWidget(self.channel_list)
vbox.addWidget(self.channel_list) # remote
vbox.addStretch(1) remote_w = QWidget()
g = QGridLayout() vbox_remote = QVBoxLayout(remote_w)
g.addWidget(HelpLabel(_('Remote Watchtower') + ':', help_remote), 1, 0) vbox_remote.addWidget(WWLabel(help_remote))
g = QGridLayout(remote_w)
g.addWidget(QLabel(_('URL') + ':'), 1, 0)
g.addWidget(self.watchtower_e, 1, 1) g.addWidget(self.watchtower_e, 1, 1)
vbox.addLayout(g) vbox_remote.addLayout(g)
vbox.addStretch(1) vbox_remote.addStretch(1)
# tabs
tabs = QTabWidget()
tabs.addTab(local_w, _('Local'))
tabs.addTab(remote_w, _('Remote'))
vbox = QVBoxLayout(self)
vbox.addWidget(tabs)
b = QPushButton(_('Close')) b = QPushButton(_('Close'))
b.clicked.connect(self.on_close) b.clicked.connect(self.on_close)
vbox.addLayout(Buttons(b)) vbox.addLayout(Buttons(b))
self.channel_list.update()
def update(self):
pass
def on_close(self): def on_close(self):
url = self.watchtower_e.text() url = self.watchtower_e.text()

10
electrum/lnwatcher.py

@ -62,6 +62,11 @@ class LNWatcher(AddressSynchronizer):
# this maps funding_outpoints to ListenerItems, which have an event for when the watcher is done, # this maps funding_outpoints to ListenerItems, which have an event for when the watcher is done,
# and a queue for seeing which txs are being published # and a queue for seeing which txs are being published
self.tx_progress = {} # type: Dict[str, ListenerItem] self.tx_progress = {} # type: Dict[str, ListenerItem]
# status gets populated when we run
self.channel_status = {}
def get_channel_status(self, outpoint):
return self.channel_status.get(outpoint, 'unknown')
def set_remote_watchtower(self): def set_remote_watchtower(self):
watchtower_url = self.config.get('watchtower_url') watchtower_url = self.config.get('watchtower_url')
@ -161,11 +166,16 @@ class LNWatcher(AddressSynchronizer):
txid = self.spent_outpoints[prev_txid].get(int(index)) txid = self.spent_outpoints[prev_txid].get(int(index))
result = {outpoint:txid} result = {outpoint:txid}
if txid is None: if txid is None:
self.channel_status[outpoint] = 'open'
self.print_error('keep watching because outpoint is unspent') self.print_error('keep watching because outpoint is unspent')
return True, result return True, result
keep_watching = (self.get_tx_mined_depth(txid) != TxMinedDepth.DEEP) keep_watching = (self.get_tx_mined_depth(txid) != TxMinedDepth.DEEP)
if keep_watching: if keep_watching:
self.channel_status[outpoint] = 'closed (%d)' % self.get_tx_height(txid).conf
self.print_error('keep watching because spending tx is not deep') self.print_error('keep watching because spending tx is not deep')
else:
self.channel_status[funding_outpoint] = 'closed (deep)'
tx = self.transactions[txid] tx = self.transactions[txid]
for i, o in enumerate(tx.outputs()): for i, o in enumerate(tx.outputs()):
if o.address not in self.get_addresses(): if o.address not in self.get_addresses():

Loading…
Cancel
Save