tlnbase: propagate error messages received in on_error to their relevant coroutines - electrum - Electrum Bitcoin wallet HTML git clone https://git.parazyd.org/electrum DIR Log DIR Files DIR Refs DIR Submodules --- DIR commit 6f3c2b30edab034c7d0cb93c6ce4d8e124f55a17 DIR parent 11c3ca281c30c7830c705c8d1295e4cd7d9d567f HTML Author: ThomasV <thomasv@electrum.org> Date: Sun, 7 Oct 2018 12:19:34 +0200 lnbase: propagate error messages received in on_error to their relevant coroutines Diffstat: M electrum/commands.py | 3 +-- M electrum/gui/qt/channels_list.py | 13 +++++++------ M electrum/lnbase.py | 11 +++++++++-- M electrum/lnworker.py | 23 ++++++++++------------- 4 files changed, 27 insertions(+), 23 deletions(-) --- DIR diff --git a/electrum/commands.py b/electrum/commands.py t@@ -766,8 +766,7 @@ class Commands: # lightning network commands @command('wpn') def open_channel(self, connection_string, amount, channel_push=0, password=None): - f = self.wallet.lnworker.open_channel(connection_string, satoshis(amount), satoshis(channel_push), password) - return f.result(5) + return self.wallet.lnworker.open_channel(connection_string, satoshis(amount), satoshis(channel_push), password) @command('wn') def reestablish_channel(self): DIR diff --git a/electrum/gui/qt/channels_list.py b/electrum/gui/qt/channels_list.py t@@ -110,11 +110,12 @@ class ChannelsList(MyTreeWidget): local_amt = local_amt_inp.get_amount() push_amt = push_amt_inp.get_amount() connect_contents = str(remote_nodeid.text()).strip() - - try: - self.main_window.protect(self.open_channel, (connect_contents, local_amt, push_amt)) - except ConnStringFormatError as e: - self.parent.show_error(str(e)) + self.main_window.protect(self.open_channel, (connect_contents, local_amt, push_amt)) def open_channel(self, *args, **kwargs): - self.parent.wallet.lnworker.open_channel(*args, **kwargs) + import traceback, sys + try: + self.parent.wallet.lnworker.open_channel(*args, **kwargs) + except Exception as e: + traceback.print_exc(file=sys.stderr) + self.parent.show_error('Cannot open channel: %s' % str(e)) DIR diff --git a/electrum/lnbase.py b/electrum/lnbase.py t@@ -406,6 +406,12 @@ class Peer(PrintError): def on_error(self, payload): self.print_error("error", payload["data"].decode("ascii")) + chan_id = payload.get("channel_id") + for d in [ self.channel_accepted, self.channel_reestablished, self.funding_signed, + self.funding_created, self.revoke_and_ack, self.commitment_signed, + self.announcement_signatures, self.closing_signed ]: + if chan_id in d: + self.channel_accepted[chan_id].put_nowait({'error':payload['data']}) def on_ping(self, payload): l = int.from_bytes(payload['num_pong_bytes'], 'big') t@@ -518,7 +524,6 @@ class Peer(PrintError): per_commitment_secret_seed = keypair_generator(LnKeyFamily.REVOCATION_ROOT).privkey return local_config, per_commitment_secret_seed - @aiosafe async def channel_establishment_flow(self, password, funding_sat, push_msat, temp_channel_id): await self.initialized local_config, per_commitment_secret_seed = self.make_local_config(funding_sat, push_msat, LOCAL) t@@ -549,6 +554,8 @@ class Peer(PrintError): ) self.send_message(msg) payload = await self.channel_accepted[temp_channel_id].get() + if payload.get('error'): + raise Exception(payload.get('error')) remote_per_commitment_point = payload['first_per_commitment_point'] remote_config=ChannelConfig( payment_basepoint=OnlyPubkeyKeypair(payload['payment_basepoint']), t@@ -1094,7 +1101,7 @@ class Peer(PrintError): self.payment_preimages[sha256(preimage)].put_nowait(preimage) def on_update_fail_malformed_htlc(self, payload): - self.on_error(payload) + self.print_error("error", payload["data"].decode("ascii")) def on_update_add_htlc(self, payload): # no onion routing for the moment: we assume we are the end node DIR diff --git a/electrum/lnworker.py b/electrum/lnworker.py t@@ -181,16 +181,13 @@ class LNWorker(PrintError): async def _open_channel_coroutine(self, peer, local_amount_sat, push_sat, password): # peer might just have been connected to await asyncio.wait_for(peer.initialized, 5) - - openingchannel = await peer.channel_establishment_flow(password, - funding_sat=local_amount_sat + push_sat, - push_msat=push_sat * 1000, - temp_channel_id=os.urandom(32)) - if not openingchannel: - self.print_error("Channel_establishment_flow returned None") - return - self.save_channel(openingchannel) - self.network.lnwatcher.watch_channel(openingchannel, partial(self.on_channel_utxos, openingchannel)) + chan = await peer.channel_establishment_flow( + password, + funding_sat=local_amount_sat + push_sat, + push_msat=push_sat * 1000, + temp_channel_id=os.urandom(32)) + self.save_channel(chan) + self.network.lnwatcher.watch_channel(chan, partial(self.on_channel_utxos, chan)) self.on_channels_updated() def on_channels_updated(self): t@@ -206,9 +203,8 @@ class LNWorker(PrintError): # TODO maybe filter out onion if not on tor? return random.choice(addr_list) - def open_channel(self, connect_contents, local_amt_sat, push_amt_sat, pw): + def open_channel(self, connect_contents, local_amt_sat, push_amt_sat, pw, timeout=5): node_id, rest = extract_nodeid(connect_contents) - peer = self.peers.get(node_id) if not peer: all_nodes = self.network.channel_db.nodes t@@ -225,7 +221,8 @@ class LNWorker(PrintError): raise ConnStringFormatError(_('Hostname does not resolve (getaddrinfo failed)')) peer = self.add_peer(host, port, node_id) coro = self._open_channel_coroutine(peer, local_amt_sat, push_amt_sat, None if pw == "" else pw) - return asyncio.run_coroutine_threadsafe(coro, self.network.asyncio_loop) + f = asyncio.run_coroutine_threadsafe(coro, self.network.asyncio_loop) + return f.result(timeout) def pay(self, invoice, amount_sat=None): addr = lndecode(invoice, expected_hrp=constants.net.SEGWIT_HRP)