commit fd8236538a955d51e0fd3268576f34fca2eaed51
parent 9c9ceb702a3a7bd0b535793db1c3478e4a402c01
Author: ThomasV <thomasv@electrum.org>
Date: Sat, 23 Nov 2019 13:30:05 +0100
Open lightning channels with partially signed tx.
Fixes #5379.
Diffstat:
5 files changed, 23 insertions(+), 11 deletions(-)
diff --git a/electrum/commands.py b/electrum/commands.py
@@ -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')
diff --git a/electrum/gui/kivy/uix/dialogs/lightning_open_channel.py b/electrum/gui/kivy/uix/dialogs/lightning_open_channel.py
@@ -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
@@ -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)
diff --git a/electrum/gui/qt/main_window.py b/electrum/gui/qt/main_window.py
@@ -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))
diff --git a/electrum/lnpeer.py b/electrum/lnpeer.py
@@ -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
@@ -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']
diff --git a/electrum/lnworker.py b/electrum/lnworker.py
@@ -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,
@@ -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:
@@ -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):
"""