The LnAddr, lndecode and lnencode naming didn't imply that it is
bolt 11 specific, making it confusing to work with, now that there are
also bolt 12 "lnaddr".
Renaming it to *bolt11* creates a clear separation to bolt 12 things and
reduces mental load.
This commit is pure renaming (using the PyCharm IDE refactor function),
except for the removal of the `object` inheritance of LnAddr/BOLT11Addr,
this is Python 2 legacy.
- could not find a single project that still actually cares about bip70 [0]
- well except maybe BitPay.
- but I cannot test with BitPay:
- they have a testnet3 staging environment on test.bitpay.com
- but the SSL cert they use for bip70 has expired in 2021
- the webUI probably also has not been updated since then...
- they claim to have added LN support in 2022 in a blog post,
but it's not there on test.bitpay.com
- on mainnet, they require KYC before payment
- < ... angry noises >
- their loss then, I don't care.
- this is code that no one wants to maintain
- this does not yet delete the signed bip70 payment data for historical txs
- but it is no longer possible to export it from the GUI
[0]: https://bitcoinops.org/en/topics/bip70-payment-protocol/
and an address is present in the bip21 uri path, register the on-chain address in the
Invoice.outputs field to allow paying onchain from a saved Invoice later (when the PI
is unavailable). Fixes#8654
- @amount_msat.validator prevents the creation of invoices with e.g. too large amounts
- however the qml gui is mutating invoices by directly setting the `amount_msat` field,
and it looks like attrs validators only run during init.
We can use `on_setattr` (introduced in attrs==20.1.0).
- a wallet db upgrade is added to rm existing insane invoices
- btw the qml gui was already doing its own input validation on the textedit
(see qeconfig.btcAmountRegex). however that only limits the input to not have more
chars than what is needed to represent 21M BTC (e.g. you can still enter 99M BTC,
which the invoice logic does not tolerate later on - but is normally caught).
fixes https://github.com/spesmilo/electrum/issues/8582
decorators (instead of overloading JsonDB._convert_dict and
_convert_value)
- stored_in for elements of a StoreDict
- stored_as for singletons
- extra register methods are defined for key conversions
This commit was adapted from the jsonpatch branch
This fixes an inconsistency where the 'expiration' field was
relative for invoices, and absolute timestamp for requests.
This in turn fixes QML the timer refreshing the request list.
In order to prevent any API using that field from being silently
broken, the 'expiration' field is renamed as 'expiry'.
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...
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.
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
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
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'
```
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'