tOpen lightning channels with partially signed tx. Fixes #5379. - electrum - Electrum Bitcoin wallet HTML git clone https://git.parazyd.org/electrum DIR Log DIR Files DIR Refs DIR Submodules --- DIR commit fd8236538a955d51e0fd3268576f34fca2eaed51 DIR parent 9c9ceb702a3a7bd0b535793db1c3478e4a402c01 HTML Author: ThomasV <thomasv@electrum.org> Date: Sat, 23 Nov 2019 13:30:05 +0100 Open lightning channels with partially signed tx. Fixes #5379. Diffstat: M electrum/commands.py | 2 +- M electrum/gui/kivy/uix/dialogs/ligh… | 6 +++++- M electrum/gui/qt/main_window.py | 8 +++++++- M electrum/lnpeer.py | 7 +++---- M electrum/lnworker.py | 11 +++++++---- 5 files changed, 23 insertions(+), 11 deletions(-) --- DIR diff --git a/electrum/commands.py b/electrum/commands.py t@@ -929,7 +929,7 @@ class Commands: push_sat = satoshis(push_amount) dummy_output = PartialTxOutput.from_address_and_value(ln_dummy_address(), funding_sat) funding_tx = wallet.mktx(outputs = [dummy_output], rbf=False, sign=False, nonlocal_only=True) - chan = await wallet.lnworker._open_channel_coroutine(connection_string, funding_tx, funding_sat, push_sat, password) + chan, funding_tx = await wallet.lnworker._open_channel_coroutine(connection_string, funding_tx, funding_sat, push_sat, password) return chan.funding_outpoint.to_str() @command('wn') DIR diff --git a/electrum/gui/kivy/uix/dialogs/lightning_open_channel.py b/electrum/gui/kivy/uix/dialogs/lightning_open_channel.py t@@ -138,7 +138,7 @@ class LightningOpenChannelDialog(Factory.Popup): def do_open_channel(self, conn_str, amount, password): try: - chan = self.app.wallet.lnworker.open_channel(conn_str, amount, 0, password=password) + chan, funding_tx = self.app.wallet.lnworker.open_channel(conn_str, amount, 0, password=password) except Exception as e: self.app.show_error(_('Problem opening channel: ') + '\n' + repr(e)) return t@@ -148,4 +148,8 @@ class LightningOpenChannelDialog(Factory.Popup): _('Remote peer ID') + ':' + chan.node_id.hex(), _('This channel will be usable after {} confirmations').format(n) ]) + if not funding_tx.is_complete(): + message += '\n\n' + _('Please sign and broadcast the funding transaction') self.app.show_info(message) + if not funding_tx.is_complete(): + self.app.tx_dialog(funding_tx) DIR diff --git a/electrum/gui/qt/main_window.py b/electrum/gui/qt/main_window.py t@@ -1636,14 +1636,20 @@ class ElectrumWindow(QMainWindow, MessageBoxMixin, Logger): funding_sat = funding_tx.output_value_for_address(ln_dummy_address()) def task(): return self.wallet.lnworker.open_channel(connect_str, funding_tx, funding_sat, push_amt, password) - def on_success(chan): + def on_success(args): + chan, funding_tx = args n = chan.constraints.funding_txn_minimum_depth message = '\n'.join([ _('Channel established.'), _('Remote peer ID') + ':' + chan.node_id.hex(), _('This channel will be usable after {} confirmations').format(n) ]) + if not funding_tx.is_complete(): + message += '\n\n' + _('Please sign and broadcast the funding transaction') self.show_message(message) + if not funding_tx.is_complete(): + self.show_transaction(funding_tx) + def on_failure(exc_info): type_, e, traceback = exc_info self.show_error(_('Could not open channel: {}').format(e)) DIR diff --git a/electrum/lnpeer.py b/electrum/lnpeer.py t@@ -575,6 +575,8 @@ class Peer(Logger): funding_tx.add_outputs([funding_output]) funding_tx.set_rbf(False) self.lnworker.wallet.sign_transaction(funding_tx, password) + if not funding_tx.is_complete() and not funding_tx.is_segwit(): + raise Exception(_('Funding transaction is not complete')) funding_txid = funding_tx.txid() funding_index = funding_tx.outputs().index(funding_output) # remote commitment transaction t@@ -605,10 +607,7 @@ class Peer(Logger): remote_sig = payload['signature'] chan.receive_new_commitment(remote_sig, []) chan.open_with_first_pcp(remote_per_commitment_point, remote_sig) - # broadcast funding tx - # TODO make more robust (timeout low? server returns error?) - await asyncio.wait_for(self.network.broadcast_transaction(funding_tx), LN_P2P_NETWORK_TIMEOUT) - return chan + return chan, funding_tx async def on_open_channel(self, payload): # payload['channel_flags'] DIR diff --git a/electrum/lnworker.py b/electrum/lnworker.py t@@ -812,7 +812,7 @@ class LNWallet(LNWorker): peer = await self.add_peer(connect_str) # peer might just have been connected to await asyncio.wait_for(peer.initialized.wait(), LN_P2P_NETWORK_TIMEOUT) - chan = await peer.channel_establishment_flow( + chan, funding_tx = await peer.channel_establishment_flow( password, funding_tx=funding_tx, funding_sat=funding_sat, t@@ -821,7 +821,10 @@ class LNWallet(LNWorker): self.save_channel(chan) self.lnwatcher.add_channel(chan.funding_outpoint.to_str(), chan.get_funding_address()) self.network.trigger_callback('channels_updated', self.wallet) - return chan + if funding_tx.is_complete(): + # TODO make more robust (timeout low? server returns error?) + await asyncio.wait_for(self.network.broadcast_transaction(funding_tx), LN_P2P_NETWORK_TIMEOUT) + return chan, funding_tx @log_exceptions async def add_peer(self, connect_str: str) -> Peer: t@@ -858,10 +861,10 @@ class LNWallet(LNWorker): coro = self._open_channel_coroutine(connect_str, funding_tx, funding_sat, push_amt_sat, password) fut = asyncio.run_coroutine_threadsafe(coro, self.network.asyncio_loop) try: - chan = fut.result(timeout=timeout) + chan, funding_tx = fut.result(timeout=timeout) except concurrent.futures.TimeoutError: raise Exception(_("open_channel timed out")) - return chan + return chan, funding_tx def pay(self, invoice, amount_sat=None, attempts=1): """