Commit Graph

41 Commits

Author SHA1 Message Date
SomberNight ad0b853cd9 invoices: improve perf by caching lnaddr even earlier
During wallet-open, we load all invoices/payreqs. This involved decoding the lnaddrs twice.
Now we only decode once.

For a wallet with ~1000 payreqs, this noticeably sped up wallet-open:
(before:)
8.83 | D | util.profiler | Daemon._load_wallet 6.4317 sec
(after:)
5.69 | D | util.profiler | Daemon._load_wallet 3.4450 sec

It is very expensive to parse all the lnaddrs...
2023-02-08 23:36:36 +00:00
SomberNight 71697afabd invoices: get_outputs to use .outputs field if available
It is wasteful to create new PartialTxOutput objects if we already have an outputs field.
Btw apparently lightning invoices too have an outputs field.
2023-02-08 00:40:46 +00:00
SomberNight 7dcaa4b204 tests: add tests for wallet/invoices functionality
only for payment requests ("incoming invoices") for now
2023-01-12 18:19:08 +00:00
SomberNight 98bf974319 invoices: fix to_debug_json: LN r_tags might be missing
>           'r_tags': [ str((a.hex(),b.hex(),c,d,e)) for a,b,c,d,e in self._lnaddr.get_routing_info('r')[-1]]
        })
E       IndexError: list index out of range
2023-01-12 18:18:56 +00:00
ThomasV d7dee45ee9 CLI: decode_invoice: show the last hop of routing hints 2023-01-10 11:57:59 +01:00
Sander van Grieken ad04ca84d8 qml: always try to generate an address for request regardless of bolt11_fallback config. 2022-11-18 18:32:43 +01:00
accumulator e0f6c18073 Favor first output address in invoice/request instead of fallback address in LN invoice. (#8078)
Without this change, when configuring electrum with bolt11_fallback disabled, and calling
invoice.get_address() on a lightning enabled invoice, it will return None, thereby disabling
retrieving BIP21 uri or address from the invoice/request.
2022-11-18 16:24:32 +00:00
SomberNight df2d0f4e1f qt send: use bolt11 fallback addr even if LN is disabled
Given a wallet with LN disabled,
and a bolt11 invoice (or a bip21 uri that only contains bolt11 but lacks a top-level address),
if the bolt11 invoice includes a fallback address,
we would previously just error "Lightning is disabled".

Now we offer the user to pay on-chain using the fallback address.

closes https://github.com/spesmilo/electrum/issues/8047
2022-10-31 19:15:03 +00:00
SomberNight eb00012c95 invoices: fix is_paid for zero-amount onchain pay reqs
fixes https://github.com/spesmilo/electrum/issues/8022
2022-10-19 16:15:12 +00:00
ThomasV 14e96f4d53 Index request by ID instead of receiving address.
Replace get_key_for_outgoing_invoice, get_key_for_incoming_request
with Invoice.get_id()

When a new request is created, reuse addresses of expired requests (fixes #7927)

The API is changed for the following commands:
 get_request, get_invoice,
 list_requests, list_invoices,
 delete_request, delete_invoice
2022-09-02 10:58:11 +02:00
ThomasV 2d6f40c8b8 fix #7935 2022-08-15 12:16:11 +02:00
SomberNight 659d6890d9 wallet.get_request_URI: rm code duplication 2022-08-11 13:07:56 +00:00
SomberNight 68581ce80a invoices: fix type hint for get_address() 2022-07-10 16:08:02 +02:00
ThomasV 917f256e33 remove scheduled invoices: bad UX. better expect the user to retry later. 2022-05-21 12:24:26 +02:00
SomberNight 2ec9e869b3 invoice.get_amount_sat: handle None in more places
I believe lightning requests created before https://github.com/spesmilo/electrum/pull/7730
can have an amount of None - ones created after have amount 0 instead.
We could do a wallet db upgrade potentially.
Regardless, the type hint is `get_amount_sat(self) -> Union[int, str, None]`,
so None should be handled. (well, arguably "!" should be handled too...)

```
E | gui.qt.exception_window.Exception_Hook | exception caught by crash reporter
Traceback (most recent call last):
  File "...\electrum\electrum\gui\qt\request_list.py", line 101, in item_changed
    self.parent.show_receive_request(req)
  File "...\electrum\electrum\gui\qt\main_window.py", line 1279, in show_receive_request
    URI = req.get_bip21_URI(lightning=bip21_lightning)
  File "...\electrum\electrum\invoices.py", line 164, in get_bip21_URI
    amount = int(self.get_amount_sat())
TypeError: int() argument must be a string, a bytes-like object or a real number, not 'NoneType'
```

```
E | gui.qt.exception_window.Exception_Hook | exception caught by crash reporter
Traceback (most recent call last):
  File "...\electrum\electrum\gui\qt\request_list.py", line 101, in item_changed
    self.parent.show_receive_request(req)
  File "...\electrum\electrum\gui\qt\main_window.py", line 1281, in show_receive_request
    can_receive_lightning = self.wallet.lnworker and req.get_amount_sat() <= self.wallet.lnworker.num_sats_can_receive()
TypeError: '<=' not supported between instances of 'NoneType' and 'decimal.Decimal'
```
2022-05-19 19:43:07 +02:00
SomberNight adfe542fae wallet_db upgrade: recalc keys of outgoing on-chain invoices
closes https://github.com/spesmilo/electrum/issues/7777
2022-04-22 19:53:55 +02:00
SomberNight 7be8b4f405 fix opening wallet that has "max" amount invoice saved
E | gui.qt.ElectrumGui |
Traceback (most recent call last):
  File "...\electrum\electrum\gui\qt\__init__.py", line 361, in start_new_window
    window = self._create_window_for_wallet(wallet)
  File "...\electrum\electrum\gui\qt\__init__.py", line 304, in _create_window_for_wallet
    w = ElectrumWindow(self, wallet)
  File "...\electrum\electrum\gui\qt\main_window.py", line 223, in __init__
    self.send_tab = self.create_send_tab()
  File "...\electrum\electrum\gui\qt\main_window.py", line 1537, in create_send_tab
    self.invoice_list = InvoiceList(self)
  File "...\electrum\electrum\gui\qt\invoice_list.py", line 76, in __init__
    self.update()
  File "...\electrum\electrum\gui\qt\invoice_list.py", line 109, in update
    amount = item.get_amount_sat()
  File "...\electrum\electrum\invoices.py", line 158, in get_amount_sat
    return int(amount_msat / 1000)
TypeError: unsupported operand type(s) for /: 'str' and 'int'
2022-04-22 16:46:06 +02:00
ThomasV ba018c707f Qt: add bolt11_fallback and bip21_lightning options to preferences 2022-04-20 12:48:22 +02:00
ThomasV 60865f3902 Show options if we do not have the liquidity to pay a lightning invoice:
pay onchain, open channel, rebalance.

If we do a swap or open a channel, the payment will be scheduled.
2022-04-20 12:48:22 +02:00
ThomasV 7102fb732e follow-up prev:
- detect payment of requests both onchain or LN
 - create single type of requests in GUI
2022-04-20 12:48:22 +02:00
ThomasV e392197ab9 wallet_db upgrade:
- unify lightning and onchain invoices, with optional fields for bip70 and lightning
 - add receive_address fields to submarine swaps
2022-04-20 12:48:22 +02:00
SomberNight acbb363240 follow-up prev: some clean-ups
re https://github.com/spesmilo/electrum/pull/7492
2021-09-15 16:41:41 +02:00
SomberNight 8a56c9eb66 invoices: explain status constants 2021-07-15 01:33:11 +02:00
SomberNight a425ab0301 invoices/lnaddr: LNInvoice.from_bech32 now raises InvoiceError
rm LnAddressError

fixes https://github.com/spesmilo/electrum/issues/7321
related https://github.com/spesmilo/electrum/pull/7234
2021-06-07 14:46:30 +02:00
bitromortac 853e912885 invoice: fail gracefully with large amount 2021-05-06 15:37:17 +02:00
ThomasV 7ca64ebbd8 fix #7078 2021-03-03 15:35:38 +01:00
SomberNight 0aa36ab5ac invoices: validate 'amount' not to be out-of-bounds 2021-02-18 06:11:09 +01:00
ThomasV 90abfda12b add unconfirmed state for onchain invoices and requests 2021-01-12 10:59:11 +01:00
ThomasV b08f9f3581 fix #6859: height is must be passed to OnchainInvoice constructor 2020-12-18 10:49:45 +01:00
SomberNight 3a7c00634e wallet_db: impl convert_version_33: put 'height' field into invoices
The 'height' field was added in https://github.com/spesmilo/electrum/commit/cdfaaa260942b807f809c2c0414fb242a03e945a
At the time we thought we could just add it with a default value without a db upgrade;
however the issue is that if old code tries to open a new db, it will fail (due to unexpected new field).
Hence it is better to do an explicit conversion where old code *knows* it cannot open the new db.

E | gui.qt.ElectrumGui |
Traceback (most recent call last):
  File "...\electrum\electrum\gui\qt\__init__.py", line 257, in start_new_window
    wallet = self.daemon.load_wallet(path, None)
  File "...\electrum\electrum\daemon.py", line 488, in load_wallet
    db = WalletDB(storage.read(), manual_upgrades=manual_upgrades)
  File "...\electrum\electrum\wallet_db.py", line 72, in __init__
    self.load_data(raw)
  File "...\electrum\electrum\wallet_db.py", line 103, in load_data
    self._after_upgrade_tasks()
  File "...\electrum\electrum\wallet_db.py", line 189, in _after_upgrade_tasks
    self._load_transactions()
  File "...\electrum\electrum\util.py", line 408, in <lambda>
    return lambda *args, **kw_args: do_profile(args, kw_args)
  File "...\electrum\electrum\util.py", line 404, in do_profile
    o = func(*args, **kw_args)
  File "...\electrum\electrum\wallet_db.py", line 1139, in _load_transactions
    self.data = StoredDict(self.data, self, [])
  File "...\electrum\electrum\json_db.py", line 79, in __init__
    self.__setitem__(k, v)
  File "...\electrum\electrum\json_db.py", line 44, in wrapper
    return func(self, *args, **kwargs)
  File "...\electrum\electrum\json_db.py", line 105, in __setitem__
    v = self.db._convert_dict(self.path, key, v)
  File "...\electrum\electrum\wallet_db.py", line 1182, in _convert_dict
    v = dict((k, Invoice.from_json(x)) for k, x in v.items())
  File "...\electrum\electrum\wallet_db.py", line 1182, in <genexpr>
    v = dict((k, Invoice.from_json(x)) for k, x in v.items())
  File "...\electrum\electrum\invoices.py", line 108, in from_json
    return OnchainInvoice(**x)
TypeError: __init__() got an unexpected keyword argument 'height'
2020-12-17 15:17:08 +01:00
ThomasV cdfaaa2609 Save height in invoices, use it to determine invoice status (fixes #6609) 2020-12-11 19:55:56 +01:00
ThomasV 2904615211 kivy: do not display internal id of onchain invoice, show address instead 2020-11-26 09:08:20 +01:00
SomberNight 46e59d18f5 invoices: rename "Pending" to "Unpaid"
related #6711
2020-11-13 19:18:34 +01:00
SomberNight 261ad804ca invoices: always validate that LNInvoice.invoice can be decoded
related: #6559

The LNInvoice.from_json() method previously did not validate, which is
used by e.g. wallet.import_invoices.
2020-09-11 19:57:42 +02:00
SomberNight dee5d52948 invoices: make sure that OnchainInvoice .exp and .time are not None
related: #6284
2020-06-27 02:27:50 +02:00
ThomasV 730bfda33a OnchainInvoice: make get_amount_sat return 0 instead of None. fixes #6203 2020-06-26 11:14:23 +02:00
SomberNight d5f368c584 LN invoices: support msat precision
fixes #6250
2020-06-22 22:48:13 +02:00
SomberNight 0b224ba685 invoices: minor clean-up (type hints, mark broken things)
also rm some dead code
2020-06-13 18:54:22 +02:00
SomberNight 309ba15745 invoices: follow-up fixes re clean-up
follow-up 6058829870 and related
2020-06-03 21:00:03 +02:00
ThomasV 0878fe08f7 do not display 'Expires in 100 years' for LN invoices 2020-06-01 22:18:08 +02:00
ThomasV 6058829870 Use attr.s classes for invoices and requests:
- storage upgrade
 - fixes #6192
 - add can_pay_invoice, can_receive_invoice to lnworker
2020-06-01 21:02:45 +02:00