mirror of
https://github.com/LBRYFoundation/LBRY-Vault.git
synced 2025-08-30 08:51:32 +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
|
||||
# SOFTWARE.
|
||||
|
||||
import queue
|
||||
import sys
|
||||
import datetime
|
||||
import copy
|
||||
|
@ -46,6 +47,7 @@ from .storage import WalletStorage
|
|||
from . import keystore
|
||||
from .wallet import Wallet, Imported_Wallet, Abstract_Wallet
|
||||
from .mnemonic import Mnemonic
|
||||
from .import lightning
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from .network import Network
|
||||
|
@ -744,6 +746,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
|
||||
|
@ -809,7 +827,8 @@ command_options = {
|
|||
'show_fiat': (None, "Show fiat value of transactions"),
|
||||
'year': (None, "Show history for a given year"),
|
||||
'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 electrum.lightning import LightningUI
|
||||
|
||||
try:
|
||||
from . import icons_rc
|
||||
|
@ -129,6 +130,11 @@ class ElectrumGui(PrintError):
|
|||
# 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
|
||||
|
|
|
@ -73,6 +73,7 @@ from .transaction_dialog import show_transaction
|
|||
from .fee_slider import FeeSlider
|
||||
from .util import *
|
||||
from .installwizard import WIF_HELP_TEXT
|
||||
from .lightning_invoice_list import LightningInvoiceList
|
||||
|
||||
|
||||
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.send_tab, QIcon(":icons/tab_send.png"), _('Send'))
|
||||
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):
|
||||
tab.tab_icon = icon
|
||||
|
@ -801,6 +804,10 @@ class ElectrumWindow(QMainWindow, MessageBoxMixin, PrintError):
|
|||
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):
|
||||
from .history_list import HistoryList
|
||||
self.history_list = l = HistoryList(self)
|
||||
|
@ -1958,6 +1965,7 @@ class ElectrumWindow(QMainWindow, MessageBoxMixin, PrintError):
|
|||
'wallet': self.wallet,
|
||||
'network': self.network,
|
||||
'plugins': self.gui_object.plugins,
|
||||
'lightning': self.gui_object.lightning,
|
||||
'window': self,
|
||||
'config': self.config,
|
||||
'electrum': electrum,
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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…
Add table
Reference in a new issue