Browse Source

lightning: complete moving of lightning objects, acquire net/wallet lock while answering lightning requests

regtest_lnd
Janus 7 years ago
committed by SomberNight
parent
commit
a0a15e2223
No known key found for this signature in database GPG Key ID: B33B5F232C6271E9
  1. 19
      electrum/commands.py
  2. 6
      electrum/gui/qt/__init__.py
  3. 8
      electrum/gui/qt/main_window.py
  4. 6
      gui/kivy/uix/dialogs/lightning_channels.py
  5. 8
      gui/kivy/uix/dialogs/lightning_payer.py
  6. 18
      lib/lightning.py

19
electrum/commands.py

@ -23,6 +23,7 @@
# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.
import queue
import sys
import datetime
import copy
@ -45,6 +46,7 @@ from .paymentrequest import PR_PAID, PR_UNPAID, PR_UNKNOWN, PR_EXPIRED
from .synchronizer import Notifier
from .wallet import Abstract_Wallet, create_new_wallet, restore_wallet_from_text
from .address_synchronizer import TX_HEIGHT_LOCAL
from .import lightning
if TYPE_CHECKING:
from .network import Network
@ -765,6 +767,22 @@ class Commands:
# for the python console
return sorted(known_commands.keys())
@command("wn")
def lightning(self, lcmd, lightningargs=None):
q = queue.Queue()
class FakeQtSignal:
def emit(self, data):
q.put(data)
class MyConsole:
new_lightning_result = FakeQtSignal()
self.wallet.network.lightningrpc.setConsole(MyConsole())
if lightningargs:
lightningargs = json_decode(lightningargs)
else:
lightningargs = []
lightning.lightningCall(self.wallet.network.lightningrpc, lcmd)(*lightningargs)
return q.get(block=True, timeout=600)
def eval_bool(x: str) -> bool:
if x == 'false': return False
@ -834,6 +852,7 @@ command_options = {
'fee_level': (None, "Float between 0.0 and 1.0, representing fee slider position"),
'from_height': (None, "Only show transactions that confirmed after given block height"),
'to_height': (None, "Only show transactions that confirmed before given block height"),
'lightningargs':(None, "Arguments for an lncli subcommand, encoded as a JSON array"),
}

6
electrum/gui/qt/__init__.py

@ -52,6 +52,7 @@ from electrum.logging import Logger
from .installwizard import InstallWizard, WalletAlreadyOpenInMemory
from electrum.lightning import LightningUI
from .util import get_default_language, read_QIcon, ColorScheme, custom_message_box
from .main_window import ElectrumWindow
@ -139,6 +140,11 @@ class ElectrumGui(Logger):
# the OS/window manager/etc might set *a dark theme*.
# Hence, try to choose colors accordingly:
ColorScheme.update_from_widget(QWidget(), force_dark=use_dark_theme)
self.lightning = LightningUI(self.set_console_and_return_lightning)
def set_console_and_return_lightning(self):
self.windows[0].wallet.network.lightningrpc.setConsole(self.windows[0].console)
return self.windows[0].wallet.network.lightningrpc
def build_tray_menu(self):
# Avoid immediate GC of old menu when window closed via its action

8
electrum/gui/qt/main_window.py

@ -87,6 +87,7 @@ from .util import (read_QIcon, ColorScheme, text_dialog, icon_path, WaitingDialo
from .installwizard import WIF_HELP_TEXT
from .history_list import HistoryList, HistoryModel
from .update_checker import UpdateCheck, UpdateCheckThread
from .lightning_invoice_list import LightningInvoiceList
class StatusBarButton(QPushButton):
@ -176,6 +177,8 @@ class ElectrumWindow(QMainWindow, MessageBoxMixin, Logger):
tabs.addTab(self.create_history_tab(), read_QIcon("tab_history.png"), _('History'))
tabs.addTab(self.send_tab, read_QIcon("tab_send.png"), _('Send'))
tabs.addTab(self.receive_tab, read_QIcon("tab_receive.png"), _('Receive'))
self.lightning_invoices_tab = self.create_lightning_invoices_tab(wallet)
tabs.addTab(self.lightning_invoices_tab, _("Lightning Invoices"))
def add_optional_tab(tabs, tab, icon, description, name):
tab.tab_icon = icon
@ -875,6 +878,10 @@ class ElectrumWindow(QMainWindow, MessageBoxMixin, Logger):
self.invoice_list.update()
self.update_completions()
def create_lightning_invoices_tab(self, wallet):
self.lightning_invoice_list = LightningInvoiceList(self, wallet.network.lightningworker, wallet.network.lightningrpc)
return self.lightning_invoice_list
def create_history_tab(self):
self.history_model = HistoryModel(self)
self.history_list = l = HistoryList(self, self.history_model)
@ -2071,6 +2078,7 @@ class ElectrumWindow(QMainWindow, MessageBoxMixin, Logger):
'wallet': self.wallet,
'network': self.network,
'plugins': self.gui_object.plugins,
'lightning': self.gui_object.lightning,
'window': self,
'config': self.config,
'electrum': electrum,

6
gui/kivy/uix/dialogs/lightning_channels.py

@ -31,12 +31,12 @@ class LightningChannelsDialog(Factory.Popup):
super(LightningChannelsDialog, self).open(*args, **kwargs)
for i in self.clocks: i.cancel()
self.clocks.append(Clock.schedule_interval(self.fetch_channels, 10))
self.app.wallet.lightning.subscribe(self.rpc_result_handler)
self.app.wallet.network.lightningrpc.subscribe(self.rpc_result_handler)
def dismiss(self, *args, **kwargs):
super(LightningChannelsDialog, self).dismiss(*args, **kwargs)
self.app.wallet.lightning.clearSubscribers()
self.app.wallet.network.lightningrpc.clearSubscribers()
def fetch_channels(self, dw):
lightning.lightningCall(self.app.wallet.lightning, "listchannels")()
lightning.lightningCall(self.app.wallet.network.lightningrpc, "listchannels")()
def rpc_result_handler(self, res):
if isinstance(res, Exception):
raise res

8
gui/kivy/uix/dialogs/lightning_payer.py

@ -47,11 +47,11 @@ class LightningPayerDialog(Factory.Popup):
def emit(self2, data):
self.app.show_info(data)
class MyConsole:
newResult = FakeQtSignal()
self.app.wallet.lightning.setConsole(MyConsole())
new_lightning_result = FakeQtSignal()
self.app.wallet.network.lightningrpc.setConsole(MyConsole())
def dismiss(self, *args, **kwargs):
super(LightningPayerDialog, self).dismiss(*args, **kwargs)
self.app.wallet.lightning.setConsole(None)
self.app.wallet.network.lightningrpc.setConsole(None)
def do_paste_sample(self):
self.invoice_data = "lnbc1pvjluezpp5qqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqypqdpl2pkx2ctnv5sxxmmwwd5kgetjypeh2ursdae8g6twvus8g6rfwvs8qun0dfjkxaq8rkx3yf5tcsyz3d73gafnh3cax9rn449d9p5uxz9ezhhypd0elx87sjle52x86fux2ypatgddc6k63n7erqz25le42c4u4ecky03ylcqca784w"
def do_paste(self):
@ -63,6 +63,6 @@ class LightningPayerDialog(Factory.Popup):
def do_clear(self):
self.invoice_data = ""
def do_pay(self):
lightning.lightningCall(self.app.wallet.lightning, "sendpayment")("--pay_req=" + self.invoice_data)
lightning.lightningCall(self.app.wallet.network.lightningrpc, "sendpayment")("--pay_req=" + self.invoice_data)
def on_lightning_qr(self):
self.app.show_info("Lightning Invoice QR scanning not implemented") #TODO

18
lib/lightning.py

@ -626,7 +626,7 @@ class LightningRPC:
traceback.print_exc()
for i in self.subscribers: applyMethodName(i)(e)
if self.console:
self.console.newResult.emit(json.dumps(toprint, indent=4))
self.console.new_lightning_result.emit(json.dumps(toprint, indent=4))
threading.Thread(target=lightningRpcNetworkRequestThreadTarget, args=(qitem, )).start()
def setConsole(self, console):
self.console = console
@ -686,7 +686,9 @@ class LightningWorker:
NETWORK = self.network()
CONFIG = self.config()
netAndWalLock.acquire()
synced, local, server = isSynced()
netAndWalLock.release()
if not synced:
await asyncio.sleep(5)
continue
@ -702,14 +704,14 @@ class LightningWorker:
writer.write(b"MAGIC")
writer.write(privateKeyHash[:6])
await asyncio.wait_for(writer.drain(), 5)
while is_running():
obj = await readJson(reader, is_running)
while True:
obj = await readJson(reader)
if not obj: continue
if "id" not in obj:
print("Invoice update?", obj)
for i in self.subscribers: i(obj)
continue
await asyncio.wait_for(readReqAndReply(obj, writer), 10)
await asyncio.wait_for(readReqAndReply(obj, writer, netAndWalLock), 10)
except:
traceback.print_exc()
await asyncio.sleep(5)
@ -717,9 +719,9 @@ class LightningWorker:
def subscribe(self, notifyFunction):
self.subscribers.append(functools.partial(notifyFunction, "LightningWorker"))
async def readJson(reader, is_running):
async def readJson(reader):
data = b""
while is_running():
while True:
newlines = sum(1 if x == b"\n"[0] else 0 for x in data)
if newlines > 1: print("Too many newlines in Electrum/lightning.py!", data)
try:
@ -731,7 +733,7 @@ async def readJson(reader, is_running):
except TimeoutError:
continue
async def readReqAndReply(obj, writer):
async def readReqAndReply(obj, writer, netAndWalLock):
methods = [
# SecretKeyRing
DerivePrivKey,
@ -760,10 +762,12 @@ async def readReqAndReply(obj, writer):
if method.__name__ == obj["method"]:
params = obj["params"][0]
print("calling method", obj["method"], "with", params)
netAndWalLock.acquire()
if asyncio.iscoroutinefunction(method):
result = await method(params)
else:
result = method(params)
netAndWalLock.release()
found = True
break
except BaseException as e:

Loading…
Cancel
Save