kivy: add option to request force-close
This commit is contained in:
@@ -15,8 +15,10 @@ from .question import Question
|
|||||||
from electrum.transaction import PartialTxOutput, Transaction
|
from electrum.transaction import PartialTxOutput, Transaction
|
||||||
from electrum.util import NotEnoughFunds, NoDynamicFeeEstimates, format_fee_satoshis, quantize_feerate
|
from electrum.util import NotEnoughFunds, NoDynamicFeeEstimates, format_fee_satoshis, quantize_feerate
|
||||||
from electrum.lnutil import ln_dummy_address
|
from electrum.lnutil import ln_dummy_address
|
||||||
|
from electrum.gui import messages
|
||||||
|
|
||||||
from .qr_dialog import QRDialog
|
from .qr_dialog import QRDialog
|
||||||
|
from .choice_dialog import ChoiceDialog
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
from ...main_window import ElectrumWindow
|
from ...main_window import ElectrumWindow
|
||||||
@@ -437,7 +439,7 @@ class ChannelBackupPopup(Popup, Logger):
|
|||||||
coro = asyncio.run_coroutine_threadsafe(self.app.wallet.lnworker.request_force_close_from_backup(self.chan.channel_id), loop)
|
coro = asyncio.run_coroutine_threadsafe(self.app.wallet.lnworker.request_force_close_from_backup(self.chan.channel_id), loop)
|
||||||
try:
|
try:
|
||||||
coro.result(5)
|
coro.result(5)
|
||||||
self.app.show_info(_('Channel closed'))
|
self.app.show_info(_('Request sent'))
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
self.logger.exception("Could not close channel")
|
self.logger.exception("Could not close channel")
|
||||||
self.app.show_info(_('Could not close channel: ') + repr(e)) # repr because str(Exception()) == ''
|
self.app.show_info(_('Could not close channel: ') + repr(e)) # repr because str(Exception()) == ''
|
||||||
@@ -490,16 +492,26 @@ class ChannelDetailsPopup(Popup, Logger):
|
|||||||
self.warning = '' if self.app.wallet.lnworker.channel_db or self.app.wallet.lnworker.is_trampoline_peer(chan.node_id) else _('Warning') + ': ' + msg
|
self.warning = '' if self.app.wallet.lnworker.channel_db or self.app.wallet.lnworker.is_trampoline_peer(chan.node_id) else _('Warning') + ': ' + msg
|
||||||
|
|
||||||
def close(self):
|
def close(self):
|
||||||
Question(_('Close channel?'), self._close).open()
|
dialog = ChoiceDialog(
|
||||||
|
title=_('Close channel'),
|
||||||
|
choices={0:_('Cooperative close'), 1:_('Request force-close')}, key=0,
|
||||||
|
callback=self._close,
|
||||||
|
description=_(messages.MSG_REQUEST_FORCE_CLOSE),
|
||||||
|
keep_choice_order=True)
|
||||||
|
dialog.open()
|
||||||
|
|
||||||
def _close(self, b):
|
def _close(self, choice):
|
||||||
if not b:
|
|
||||||
return
|
|
||||||
loop = self.app.wallet.network.asyncio_loop
|
loop = self.app.wallet.network.asyncio_loop
|
||||||
coro = asyncio.run_coroutine_threadsafe(self.app.wallet.lnworker.close_channel(self.chan.channel_id), loop)
|
if choice == 1:
|
||||||
|
coro = self.app.wallet.lnworker.request_force_close_from_backup(self.chan.channel_id)
|
||||||
|
msg = _('Request sent')
|
||||||
|
else:
|
||||||
|
coro = self.app.wallet.lnworker.close_channel(self.chan.channel_id)
|
||||||
|
msg = _('Channel closed')
|
||||||
|
f = asyncio.run_coroutine_threadsafe(coro, loop)
|
||||||
try:
|
try:
|
||||||
coro.result(5)
|
f.result(5)
|
||||||
self.app.show_info(_('Channel closed'))
|
self.app.show_info(msg)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
self.logger.exception("Could not close channel")
|
self.logger.exception("Could not close channel")
|
||||||
self.app.show_info(_('Could not close channel: ') + repr(e)) # repr because str(Exception()) == ''
|
self.app.show_info(_('Could not close channel: ') + repr(e)) # repr because str(Exception()) == ''
|
||||||
|
|||||||
@@ -1,14 +1,11 @@
|
|||||||
# note: qt and kivy use different i18n methods
|
# note: qt and kivy use different i18n methods
|
||||||
|
|
||||||
MSG_RECOVERABLE_CHANNELS = """
|
MSG_RECOVERABLE_CHANNELS = """
|
||||||
Add extra data to your channel funding transactions, so that a static backup can be
|
Add extra data to your channel funding transactions, so that a static backup can be recovered from your seed.
|
||||||
recovered from your seed.
|
|
||||||
|
|
||||||
Note that static backups only allow you to request a force-close with the remote node.
|
Note that static backups only allow you to request a force-close with the remote node. This assumes that the remote node is still online, did not lose its data, and accepts to force close the channel.
|
||||||
This assumes that the remote node is still online, did not lose its data, and accepts
|
|
||||||
to force close the channel.
|
|
||||||
|
|
||||||
If this is enabled, other nodes cannot open a channel to you. Channel recovery data
|
If this is enabled, other nodes cannot open a channel to you. Channel recovery data is encrypted, so that only your wallet can decrypt it. However, blockchain analysis will be able to tell that the transaction was probably created by Electrum.
|
||||||
is encrypted, so that only your wallet can decrypt it. However, blockchain analysis
|
|
||||||
will be able to tell that the transaction was probably created by Electrum.
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
MSG_REQUEST_FORCE_CLOSE = """If you choose to request force-close, your node will pretend that it has lost its data and ask the remote node to broadcast their latest state. Doing so from time to time helps make sure that nodes are honest, because your node can punish them if they broadcast a revoked state."""
|
||||||
|
|||||||
@@ -16,6 +16,7 @@ from electrum.wallet import Abstract_Wallet
|
|||||||
from electrum.lnutil import LOCAL, REMOTE, format_short_channel_id, LN_MAX_FUNDING_SAT
|
from electrum.lnutil import LOCAL, REMOTE, format_short_channel_id, LN_MAX_FUNDING_SAT
|
||||||
from electrum.lnworker import LNWallet
|
from electrum.lnworker import LNWallet
|
||||||
from electrum import ecc
|
from electrum import ecc
|
||||||
|
from electrum.gui import messages
|
||||||
|
|
||||||
from .util import (MyTreeView, WindowModalDialog, Buttons, OkButton, CancelButton,
|
from .util import (MyTreeView, WindowModalDialog, Buttons, OkButton, CancelButton,
|
||||||
EnterButton, WaitingDialog, MONOSPACE_FONT, ColorScheme)
|
EnterButton, WaitingDialog, MONOSPACE_FONT, ColorScheme)
|
||||||
@@ -111,9 +112,7 @@ class ChannelsList(MyTreeView):
|
|||||||
self.is_force_close = False
|
self.is_force_close = False
|
||||||
msg = _('Close channel?')
|
msg = _('Close channel?')
|
||||||
force_cb = QCheckBox('Request force close from remote peer')
|
force_cb = QCheckBox('Request force close from remote peer')
|
||||||
tooltip = _(
|
tooltip = _(messages.MSG_REQUEST_FORCE_CLOSE)
|
||||||
'If you check this option, your node will pretend that it has lost its data and ask the remote node to broadcast their latest state. '
|
|
||||||
'Doing so from time to time helps make sure that nodes are honest, because your node can punish them if they broadcast a revoked state.')
|
|
||||||
tooltip = '<qt>' + tooltip + '</qt>' # rich text is word wrapped
|
tooltip = '<qt>' + tooltip + '</qt>' # rich text is word wrapped
|
||||||
def on_checked(b):
|
def on_checked(b):
|
||||||
self.is_force_close = bool(b)
|
self.is_force_close = bool(b)
|
||||||
|
|||||||
Reference in New Issue
Block a user