ln: do not add_peer in open_channel, but add_peer in gui when opening channel to unknown peer

This commit is contained in:
Janus 2018-06-29 16:22:32 +01:00
parent 0b7f4eb83c
commit 839c2fa46d
3 changed files with 84 additions and 20 deletions

View File

@ -1,6 +1,7 @@
# -*- coding: utf-8 -*-
from PyQt5 import QtCore, QtWidgets
from PyQt5.QtWidgets import *
import concurrent.futures
from electrum.util import inv_dict, bh2u, bfh
from electrum.i18n import _
@ -84,7 +85,7 @@ class ChannelsList(MyTreeWidget):
push_amt_inp.setAmount(0)
h.addWidget(QLabel(_('Your Node ID')), 0, 0)
h.addWidget(local_nodeid, 0, 1)
h.addWidget(QLabel(_('Remote Node ID')), 1, 0)
h.addWidget(QLabel(_('Remote Node ID or connection string')), 1, 0)
h.addWidget(remote_nodeid, 1, 1)
h.addWidget(QLabel('Local amount'), 2, 0)
h.addWidget(local_amt_inp, 2, 1)
@ -94,20 +95,80 @@ class ChannelsList(MyTreeWidget):
vbox.addLayout(Buttons(CancelButton(d), OkButton(d)))
if not d.exec_():
return
nodeid_hex = str(remote_nodeid.text())
local_amt = local_amt_inp.get_amount()
push_amt = push_amt_inp.get_amount()
connect_contents = str(remote_nodeid.text())
rest = None
try:
nodeid_hex, rest = connect_contents.split("@")
except ValueError:
nodeid_hex = connect_contents
try:
node_id = bfh(nodeid_hex)
assert len(node_id) == 33
except:
self.parent.show_error(_('Invalid node ID'))
self.parent.show_error(_('Invalid node ID, must be 33 bytes and hexadecimal'))
return
if node_id not in self.parent.wallet.lnworker.peers and node_id not in self.parent.network.lightning_nodes:
local_amt = local_amt_inp.get_amount()
push_amt = push_amt_inp.get_amount()
if local_amt < 200000:
self.parent.show_error(_('You must specify an decent amount (>=2 mBTC) for ' + \
'the initial local balance of the channel.'))
return
known = node_id in self.parent.network.lightning_nodes
connected = node_id in self.parent.wallet.lnworker.peers
open_channel_info = (node_id, local_amt, push_amt)
if connected:
peer = self.parent.wallet.lnworker.peers[node_id]
if not peer.initialized.done():
self.parent.show_error(_('Peer not initialized'))
return
self.gui_open_channel(None, peer, open_channel_info)
return
if rest is not None: # perfer ip/port from input field
try:
host, port = rest.split(":")
except ValueError:
self.parent.show_error(_('Connection strings must be in <node_pubkey>@<host>:<port> format'))
elif known: # then use config file
node = self.network.lightning_nodes.get(node_id)
host, port = node['addresses'][0]
else:
self.parent.show_error(_('Unknown node:') + ' ' + nodeid_hex)
return
assert local_amt >= 200000
assert local_amt >= push_amt
self.main_window.protect(self.open_channel, (node_id, local_amt, push_amt))
try:
int(port)
except:
self.parent.show_error(_('Port number must be decimal'))
return
peer, coro = self.parent.wallet.lnworker.add_peer(host, port, node_id, aiosafe=False)
q = QtCore.QTimer()
q.singleShot(3000, lambda: self.gui_open_channel(coro, peer, open_channel_info))
def gui_open_channel(self, coro, peer, open_channel_info):
if coro is not None:
try:
raise coro.exception(timeout=0)
except concurrent.futures.TimeoutError:
pass
except concurrent.futures.CancelledError:
print("Ignoring CancelledError, probably shutting down since main_loop cancelled...")
return
except Exception as e:
self.parent.show_error(_('LN main loop threw:') + ' ' + str(e))
return
if not peer.initialized.done():
self.parent.show_error(_('Peer not initialized within 3 seconds'))
return
self.main_window.protect(self.open_channel, open_channel_info)
def open_channel(self, *args, **kwargs):
self.parent.wallet.lnworker.open_channel(*args, **kwargs)

View File

@ -479,6 +479,9 @@ class Peer(PrintError):
@aiosafe
async def main_loop(self):
return await self._main_loop()
async def _main_loop(self):
self.reader, self.writer = await asyncio.open_connection(self.host, self.port)
await self.handshake()
# send init

View File

@ -52,11 +52,16 @@ class LNWorker(PrintError):
assert type(node_id) is bytes
return {x: y for (x, y) in self.channels.items() if y.node_id == node_id}
def add_peer(self, host, port, node_id):
def add_peer(self, host, port, node_id, aiosafe=True):
peer = Peer(self, host, int(port), node_id, request_initial_sync=self.config.get("request_initial_sync", True))
self.network.futures.append(asyncio.run_coroutine_threadsafe(peer.main_loop(), asyncio.get_event_loop()))
if not aiosafe:
method = peer._main_loop
else:
method = peer.main_loop
coro = asyncio.run_coroutine_threadsafe(method(), asyncio.get_event_loop())
self.network.futures.append(coro)
self.peers[node_id] = peer
self.lock = threading.Lock()
return peer, coro
def save_channel(self, openchannel):
assert type(openchannel) is HTLCStateMachine
@ -115,15 +120,10 @@ class LNWorker(PrintError):
conf = self.wallet.get_tx_height(chan.funding_outpoint.txid)[1]
peer.on_network_update(chan, conf)
async def _open_channel_coroutine(self, node_id, amount_sat, push_sat, password):
if node_id not in self.peers:
node = self.network.lightning_nodes.get(node_id)
if node is None:
return "node not found, peers available are: " + str(self.network.lightning_nodes.keys())
host, port = node['addresses'][0]
self.add_peer(host, port, node_id)
async def _open_channel_coroutine(self, node_id, local_amount_sat, push_sat, password):
peer = self.peers[node_id]
openingchannel = await peer.channel_establishment_flow(self.wallet, self.config, password, amount_sat, push_sat * 1000, temp_channel_id=os.urandom(32))
openingchannel = await peer.channel_establishment_flow(self.wallet, self.config, password, local_amount_sat + push_sat, push_sat * 1000, temp_channel_id=os.urandom(32))
self.save_channel(openingchannel)
self.on_channels_updated()