mirror of
https://github.com/LBRYFoundation/LBRY-Vault.git
synced 2025-08-30 17:01:34 +00:00
lightning: complete moving of lightning objects, acquire net/wallet lock while answering lightning requests
This commit is contained in:
parent
cf2ec480cc
commit
df910ec1de
6 changed files with 52 additions and 15 deletions
|
@ -23,6 +23,7 @@
|
||||||
# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
# SOFTWARE.
|
# SOFTWARE.
|
||||||
|
|
||||||
|
import queue
|
||||||
import sys
|
import sys
|
||||||
import datetime
|
import datetime
|
||||||
import copy
|
import copy
|
||||||
|
@ -46,6 +47,7 @@ from .storage import WalletStorage
|
||||||
from . import keystore
|
from . import keystore
|
||||||
from .wallet import Wallet, Imported_Wallet, Abstract_Wallet
|
from .wallet import Wallet, Imported_Wallet, Abstract_Wallet
|
||||||
from .mnemonic import Mnemonic
|
from .mnemonic import Mnemonic
|
||||||
|
from .import lightning
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
from .network import Network
|
from .network import Network
|
||||||
|
@ -744,6 +746,22 @@ class Commands:
|
||||||
# for the python console
|
# for the python console
|
||||||
return sorted(known_commands.keys())
|
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:
|
def eval_bool(x: str) -> bool:
|
||||||
if x == 'false': return False
|
if x == 'false': return False
|
||||||
|
@ -809,7 +827,8 @@ command_options = {
|
||||||
'show_fiat': (None, "Show fiat value of transactions"),
|
'show_fiat': (None, "Show fiat value of transactions"),
|
||||||
'year': (None, "Show history for a given year"),
|
'year': (None, "Show history for a given year"),
|
||||||
'fee_method': (None, "Fee estimation method to use"),
|
'fee_method': (None, "Fee estimation method to use"),
|
||||||
'fee_level': (None, "Float between 0.0 and 1.0, representing fee slider position")
|
'fee_level': (None, "Float between 0.0 and 1.0, representing fee slider position"),
|
||||||
|
'lightningargs':(None, "Arguments for an lncli subcommand, encoded as a JSON array"),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -47,6 +47,7 @@ from electrum.util import (UserCancelled, PrintError,
|
||||||
|
|
||||||
from .installwizard import InstallWizard
|
from .installwizard import InstallWizard
|
||||||
|
|
||||||
|
from electrum.lightning import LightningUI
|
||||||
|
|
||||||
try:
|
try:
|
||||||
from . import icons_rc
|
from . import icons_rc
|
||||||
|
@ -129,6 +130,11 @@ class ElectrumGui(PrintError):
|
||||||
# the OS/window manager/etc might set *a dark theme*.
|
# the OS/window manager/etc might set *a dark theme*.
|
||||||
# Hence, try to choose colors accordingly:
|
# Hence, try to choose colors accordingly:
|
||||||
ColorScheme.update_from_widget(QWidget(), force_dark=use_dark_theme)
|
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):
|
def build_tray_menu(self):
|
||||||
# Avoid immediate GC of old menu when window closed via its action
|
# Avoid immediate GC of old menu when window closed via its action
|
||||||
|
|
|
@ -73,6 +73,7 @@ from .transaction_dialog import show_transaction
|
||||||
from .fee_slider import FeeSlider
|
from .fee_slider import FeeSlider
|
||||||
from .util import *
|
from .util import *
|
||||||
from .installwizard import WIF_HELP_TEXT
|
from .installwizard import WIF_HELP_TEXT
|
||||||
|
from .lightning_invoice_list import LightningInvoiceList
|
||||||
|
|
||||||
|
|
||||||
class StatusBarButton(QPushButton):
|
class StatusBarButton(QPushButton):
|
||||||
|
@ -159,6 +160,8 @@ class ElectrumWindow(QMainWindow, MessageBoxMixin, PrintError):
|
||||||
tabs.addTab(self.create_history_tab(), QIcon(":icons/tab_history.png"), _('History'))
|
tabs.addTab(self.create_history_tab(), QIcon(":icons/tab_history.png"), _('History'))
|
||||||
tabs.addTab(self.send_tab, QIcon(":icons/tab_send.png"), _('Send'))
|
tabs.addTab(self.send_tab, QIcon(":icons/tab_send.png"), _('Send'))
|
||||||
tabs.addTab(self.receive_tab, QIcon(":icons/tab_receive.png"), _('Receive'))
|
tabs.addTab(self.receive_tab, QIcon(":icons/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):
|
def add_optional_tab(tabs, tab, icon, description, name):
|
||||||
tab.tab_icon = icon
|
tab.tab_icon = icon
|
||||||
|
@ -801,6 +804,10 @@ class ElectrumWindow(QMainWindow, MessageBoxMixin, PrintError):
|
||||||
self.invoice_list.update()
|
self.invoice_list.update()
|
||||||
self.update_completions()
|
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):
|
def create_history_tab(self):
|
||||||
from .history_list import HistoryList
|
from .history_list import HistoryList
|
||||||
self.history_list = l = HistoryList(self)
|
self.history_list = l = HistoryList(self)
|
||||||
|
@ -1958,6 +1965,7 @@ class ElectrumWindow(QMainWindow, MessageBoxMixin, PrintError):
|
||||||
'wallet': self.wallet,
|
'wallet': self.wallet,
|
||||||
'network': self.network,
|
'network': self.network,
|
||||||
'plugins': self.gui_object.plugins,
|
'plugins': self.gui_object.plugins,
|
||||||
|
'lightning': self.gui_object.lightning,
|
||||||
'window': self,
|
'window': self,
|
||||||
'config': self.config,
|
'config': self.config,
|
||||||
'electrum': electrum,
|
'electrum': electrum,
|
||||||
|
|
|
@ -31,12 +31,12 @@ class LightningChannelsDialog(Factory.Popup):
|
||||||
super(LightningChannelsDialog, self).open(*args, **kwargs)
|
super(LightningChannelsDialog, self).open(*args, **kwargs)
|
||||||
for i in self.clocks: i.cancel()
|
for i in self.clocks: i.cancel()
|
||||||
self.clocks.append(Clock.schedule_interval(self.fetch_channels, 10))
|
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):
|
def dismiss(self, *args, **kwargs):
|
||||||
super(LightningChannelsDialog, self).dismiss(*args, **kwargs)
|
super(LightningChannelsDialog, self).dismiss(*args, **kwargs)
|
||||||
self.app.wallet.lightning.clearSubscribers()
|
self.app.wallet.network.lightningrpc.clearSubscribers()
|
||||||
def fetch_channels(self, dw):
|
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):
|
def rpc_result_handler(self, res):
|
||||||
if isinstance(res, Exception):
|
if isinstance(res, Exception):
|
||||||
raise res
|
raise res
|
||||||
|
|
|
@ -47,11 +47,11 @@ class LightningPayerDialog(Factory.Popup):
|
||||||
def emit(self2, data):
|
def emit(self2, data):
|
||||||
self.app.show_info(data)
|
self.app.show_info(data)
|
||||||
class MyConsole:
|
class MyConsole:
|
||||||
newResult = FakeQtSignal()
|
new_lightning_result = FakeQtSignal()
|
||||||
self.app.wallet.lightning.setConsole(MyConsole())
|
self.app.wallet.network.lightningrpc.setConsole(MyConsole())
|
||||||
def dismiss(self, *args, **kwargs):
|
def dismiss(self, *args, **kwargs):
|
||||||
super(LightningPayerDialog, self).dismiss(*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):
|
def do_paste_sample(self):
|
||||||
self.invoice_data = "lnbc1pvjluezpp5qqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqypqdpl2pkx2ctnv5sxxmmwwd5kgetjypeh2ursdae8g6twvus8g6rfwvs8qun0dfjkxaq8rkx3yf5tcsyz3d73gafnh3cax9rn449d9p5uxz9ezhhypd0elx87sjle52x86fux2ypatgddc6k63n7erqz25le42c4u4ecky03ylcqca784w"
|
self.invoice_data = "lnbc1pvjluezpp5qqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqypqdpl2pkx2ctnv5sxxmmwwd5kgetjypeh2ursdae8g6twvus8g6rfwvs8qun0dfjkxaq8rkx3yf5tcsyz3d73gafnh3cax9rn449d9p5uxz9ezhhypd0elx87sjle52x86fux2ypatgddc6k63n7erqz25le42c4u4ecky03ylcqca784w"
|
||||||
def do_paste(self):
|
def do_paste(self):
|
||||||
|
@ -63,6 +63,6 @@ class LightningPayerDialog(Factory.Popup):
|
||||||
def do_clear(self):
|
def do_clear(self):
|
||||||
self.invoice_data = ""
|
self.invoice_data = ""
|
||||||
def do_pay(self):
|
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):
|
def on_lightning_qr(self):
|
||||||
self.app.show_info("Lightning Invoice QR scanning not implemented") #TODO
|
self.app.show_info("Lightning Invoice QR scanning not implemented") #TODO
|
||||||
|
|
|
@ -626,7 +626,7 @@ class LightningRPC:
|
||||||
traceback.print_exc()
|
traceback.print_exc()
|
||||||
for i in self.subscribers: applyMethodName(i)(e)
|
for i in self.subscribers: applyMethodName(i)(e)
|
||||||
if self.console:
|
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()
|
threading.Thread(target=lightningRpcNetworkRequestThreadTarget, args=(qitem, )).start()
|
||||||
def setConsole(self, console):
|
def setConsole(self, console):
|
||||||
self.console = console
|
self.console = console
|
||||||
|
@ -686,7 +686,9 @@ class LightningWorker:
|
||||||
NETWORK = self.network()
|
NETWORK = self.network()
|
||||||
CONFIG = self.config()
|
CONFIG = self.config()
|
||||||
|
|
||||||
|
netAndWalLock.acquire()
|
||||||
synced, local, server = isSynced()
|
synced, local, server = isSynced()
|
||||||
|
netAndWalLock.release()
|
||||||
if not synced:
|
if not synced:
|
||||||
await asyncio.sleep(5)
|
await asyncio.sleep(5)
|
||||||
continue
|
continue
|
||||||
|
@ -702,14 +704,14 @@ class LightningWorker:
|
||||||
writer.write(b"MAGIC")
|
writer.write(b"MAGIC")
|
||||||
writer.write(privateKeyHash[:6])
|
writer.write(privateKeyHash[:6])
|
||||||
await asyncio.wait_for(writer.drain(), 5)
|
await asyncio.wait_for(writer.drain(), 5)
|
||||||
while is_running():
|
while True:
|
||||||
obj = await readJson(reader, is_running)
|
obj = await readJson(reader)
|
||||||
if not obj: continue
|
if not obj: continue
|
||||||
if "id" not in obj:
|
if "id" not in obj:
|
||||||
print("Invoice update?", obj)
|
print("Invoice update?", obj)
|
||||||
for i in self.subscribers: i(obj)
|
for i in self.subscribers: i(obj)
|
||||||
continue
|
continue
|
||||||
await asyncio.wait_for(readReqAndReply(obj, writer), 10)
|
await asyncio.wait_for(readReqAndReply(obj, writer, netAndWalLock), 10)
|
||||||
except:
|
except:
|
||||||
traceback.print_exc()
|
traceback.print_exc()
|
||||||
await asyncio.sleep(5)
|
await asyncio.sleep(5)
|
||||||
|
@ -717,9 +719,9 @@ class LightningWorker:
|
||||||
def subscribe(self, notifyFunction):
|
def subscribe(self, notifyFunction):
|
||||||
self.subscribers.append(functools.partial(notifyFunction, "LightningWorker"))
|
self.subscribers.append(functools.partial(notifyFunction, "LightningWorker"))
|
||||||
|
|
||||||
async def readJson(reader, is_running):
|
async def readJson(reader):
|
||||||
data = b""
|
data = b""
|
||||||
while is_running():
|
while True:
|
||||||
newlines = sum(1 if x == b"\n"[0] else 0 for x in data)
|
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)
|
if newlines > 1: print("Too many newlines in Electrum/lightning.py!", data)
|
||||||
try:
|
try:
|
||||||
|
@ -731,7 +733,7 @@ async def readJson(reader, is_running):
|
||||||
except TimeoutError:
|
except TimeoutError:
|
||||||
continue
|
continue
|
||||||
|
|
||||||
async def readReqAndReply(obj, writer):
|
async def readReqAndReply(obj, writer, netAndWalLock):
|
||||||
methods = [
|
methods = [
|
||||||
# SecretKeyRing
|
# SecretKeyRing
|
||||||
DerivePrivKey,
|
DerivePrivKey,
|
||||||
|
@ -760,10 +762,12 @@ async def readReqAndReply(obj, writer):
|
||||||
if method.__name__ == obj["method"]:
|
if method.__name__ == obj["method"]:
|
||||||
params = obj["params"][0]
|
params = obj["params"][0]
|
||||||
print("calling method", obj["method"], "with", params)
|
print("calling method", obj["method"], "with", params)
|
||||||
|
netAndWalLock.acquire()
|
||||||
if asyncio.iscoroutinefunction(method):
|
if asyncio.iscoroutinefunction(method):
|
||||||
result = await method(params)
|
result = await method(params)
|
||||||
else:
|
else:
|
||||||
result = method(params)
|
result = method(params)
|
||||||
|
netAndWalLock.release()
|
||||||
found = True
|
found = True
|
||||||
break
|
break
|
||||||
except BaseException as e:
|
except BaseException as e:
|
||||||
|
|
Loading…
Add table
Reference in a new issue