1
0
Commit Graph

59 Commits

Author SHA1 Message Date
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
SomberNight
7b8e257ebb wallet db upgrade: rm support of "legacy" lightning channels
("legacy" as in pre-static-remote-key channels)
2022-08-16 08:49:17 +02:00
SomberNight
ed65f335bd wallet_db upgrade: fix possible corruption of invoice amounts
see https://github.com/spesmilo/electrum/pull/7774
2022-07-15 18:26:13 +02:00
ThomasV
9fe93524b7 Index lightning requests with rhash instead of onchain address.
get_unused_addresses() has been broken since #7730, because
addresses are considered as permanently used if they are in
the list of keys of receive_requests. This is true even if
an address is used as fallback for a lightning payment. This
means that the number of lightning payments we can receive
is constrained by the gap limit.

If a payment succeeds off-chain, we want to be able to reuse
its fallback address in other requests (this does not reduce
privacy, because invoices already share the same public key).

This implies that we should not use the onchain address as key
for lightning-enabled requests in wallet.receive_requests. If
we did, paid invoices would be overwritten when the address is
reused. That is the reason for the wallet_db upgrade.

Related: a3faf85e3c
2022-06-15 18:44:52 +02:00
SomberNight
cbc69742b9 wallet_db: clarify hww types in old upgrades
There is no point in adding new hww types to these lists every time support for a new hww is added.
These upgrades got released in 2.7.0 and any hw types added after are unrelated.

reverted to just-after last relevant change:
c820423b00
2022-05-11 19:50:57 +02:00
SomberNight
cfa6b91f22 wallet_db: rm dependence on PaymentRequest class in convert_version_25
Change convert_version_25 to delete invoices instead of converting them.
convert_version_25 was released ~2 years ago. Wallet files not opened since will have old bip70 invoices deleted upon upgrading.

In general it is ~unsafe for convert_version_* to depend on other modules of the code.
(using e.g. sha256 is fine as its API will never change,
but using e.g. PaymentRequest is dangerous as its API might change over time)
2022-04-23 20:15:10 +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
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
03df14b27a wallet_db: handle legacy channels in convert_version_44
I still have a mainnet wallet with some pre-static-remotekey channels
(though those channels are closed) that I do not want to delete yet.

follow-up https://github.com/spesmilo/electrum/pull/7636

```
E | gui.qt.exception_window.Exception_Hook | exception caught by crash reporter
Traceback (most recent call last):
  File "...\electrum\electrum\gui\qt\__init__.py", line 307, in wrapper
    return func(self, *args, **kwargs)
  File "...\electrum\electrum\gui\qt\__init__.py", line 332, in start_new_window
    wallet = self._start_wizard_to_select_or_create_wallet(path)
  File "...\electrum\electrum\gui\qt\__init__.py", line 377, in _start_wizard_to_select_or_create_wallet
    db = WalletDB(storage.read(), manual_upgrades=False)
  File "...\electrum\electrum\wallet_db.py", line 73, in __init__
    self.load_data(raw)
  File "...\electrum\electrum\wallet_db.py", line 106, in load_data
    self.upgrade()
  File "...\electrum\electrum\util.py", line 439, in <lambda>
    return lambda *args, **kw_args: do_profile(args, kw_args)
  File "...\electrum\electrum\util.py", line 435, in do_profile
    o = func(*args, **kw_args)
  File "...\electrum\electrum\wallet_db.py", line 195, in upgrade
    self._convert_version_44()
  File "...\electrum\electrum\wallet_db.py", line 859, in _convert_version_44
    if item['static_remotekey_enabled']:
KeyError: 'static_remotekey_enabled'
```
2022-02-25 20:44:05 +01:00
bitromortac
db86aeb83a wallet: replace static remotekey with channel type 2022-01-20 16:47:49 +01:00
bitromortac
6915e3cb10 lnpeer+wallet: use channel type for channel open
* channel_type is put into storage, serialized as int and
  deserialized as ChannelType
* check for static_remotekey is done via channel type
2022-01-20 16:47:48 +01:00
SomberNight
88a1c1a618 python 3.10: fix some deprecation warnings and compat with 3.10 2021-11-09 01:02:57 +01:00
ThomasV
b431d8e9b8 follow-up eadd1bebb2 2021-09-24 17:36:33 +02:00
ThomasV
eadd1bebb2 Do not convert StoredDict keys to str.
Instead, convert json keys to int when storage is read.
2021-09-20 14:49:59 +02:00
ThomasV
7a0904c0f4 wallet update: move fields that have string keys out of channel log 2021-09-20 14:47:20 +02:00
SomberNight
1188187431 wallet_db upgrade: in OnchainInvoice['outputs'], convert vals None->0
should fix https://github.com/spesmilo/electrum/issues/7500
2021-09-19 17:35:49 +02:00
SomberNight
b7cdf3fe11 wallet_db upgrades: (trivial) make upgrades more standalone
and robust to code changes
2021-09-19 17:32:25 +02:00
SomberNight
34c2cb5220 wallet: fix channels backups in .backup files
This is a regression from 64a931f21e,
which introduced "onchain_channel_backups", and renamed
the old "channel_backups" key to "imported_channel_backups".

The `save_backup` method was not changed to use the new "imported_channel_backups" key,
so the channel backups are in the backup file but they are ignored.
2021-06-08 16:21:43 +02:00
SomberNight
7b7bba2299 wallet_db: put 'seed_type' into keystores (incl db upgrade) 2021-03-30 21:16:14 +02:00
Benoit Verret
f731c38293 Minor style changes 2021-03-21 00:36:23 -04:00
ThomasV
64a931f21e Deterministic NodeID:
- use_recoverable_channel is a user setting, available
   only in standard wallets with a 'segwit' seed_type
 - if enabled, 'lightning_xprv' is derived from seed
 - otherwise, wallets use the existing 'lightning_privkey2'

Recoverable channels:
 - channel recovery data is added funding tx using an OP_RETURN
 - recovery data = 4 magic bytes + node id[0:16]
 - recovery data is chacha20 encrypted using funding_address as nonce.
   (this will allow to fund multiple channels in the same tx)

GUI:
  - whether channels are recoverable is shown in wallet info dialog.
  - if the wallet can have recoverable channels but has an old node_id,
    users are told to close their channels and restore from seed
    to have that feature.
2021-03-19 10:17:02 +01:00
SomberNight
0aa36ab5ac invoices: validate 'amount' not to be out-of-bounds 2021-02-18 06:11:09 +01:00
SomberNight
b080df9cff wallet.bump_fee: (fix) make sure input signatures are removed
bump_fee was returning an invalid tx if its input was a
PartialTransaction that had signatures. It was relying on
line 1441 to remove signatures.

Relatedly, the WalletDB used to store such PartialTransactions as
PartialTransaction objects, but only until the program was restarted.
This is because serialising and de-serialising such a tx results in a
Transaction object.

So, combining these two, to reproduce a bug:
- create a tx, sign it, save as local
- bump fee, sign it, save as local
- bump fee --> tx already signed!? --> has old sigs, so it is invalid
2021-02-15 10:20:30 +01:00
ThomasV
e477a43385 PaymentInfo: use msat precision 2021-02-01 15:03:56 +01:00
SomberNight
27cd078001 wallet: auto-freeze small unconfirmed UTXOs
see #6960
2021-01-29 12:37:15 +01:00
ThomasV
3cb68b10b9 remove broken payment requests. fixes #6350 2021-01-12 14:57:31 +01:00
bitromortac
e5458bb534 wallet_db: migrate to upfront shutdown scripts 2021-01-11 11:37:14 +01:00
Malcolm Smith
67ae678137 storage/db: use faster JSON encoder settings when wallet is encrypted
The standard json module has an optimized C encoder, but that doesn't
currently support indentation. So if you request indentation, it falls
back on the slower Python encoder.

Readability doesn't matter for encrypted wallets, so this disables
indentation when the wallet is encrypted.

-----

based on b2399b6a3e

For a large encrypted wallet, compare:
before change:
JsonDB.dump 1.3153 sec
zlib.compress 1.281 sec
ECPubkey.encrypt_message 0.1744 sec

after change:
JsonDB.dump 0.5059 sec
zlib.compress 1.3120 sec
ECPubkey.encrypt_message 0.1630 sec

Co-authored-by: SomberNight <somber.night@protonmail.com>
2021-01-06 21:14:56 +01:00
ThomasV
89ecc85c64 convert_version_24: loop over list instead of dict items (see #6863 and #6349) 2020-12-18 14:30:47 +01:00
SomberNight
3a7c00634e wallet_db: impl convert_version_33: put 'height' field into invoices
The 'height' field was added in cdfaaa2609
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
SomberNight
da6080421e wallet_db: WalletDB.get_txo_addr now returns dict instead of list 2020-10-18 20:37:25 +02:00
SomberNight
4b6c86ecbe wallet: make labels private, and access to need lock
e.g. labels plugin iterated over wallet.labels on asyncio thread while user could trigger an edit from Qt thread
2020-10-13 18:57:55 +02:00
SomberNight
a7199696d3 json_db: exempt keystore from StoredDict conversion
The keystore logic would need to be significantly changed to nicely
interoperate with StoredDict/json_db logic.
(just see KeyStore.__init__() and KeyStore.dump())
For now we exempt the keystore from the recursive StoredDict conversion, as
it is a smaller change that is also easier to review for correctness.

fixes #6066
fixes #6401

also reverts 2d3c2eeea9 (which was an even hackier workaround for #6066)
2020-09-04 16:11:01 +02:00
SomberNight
307403a02c invoices: rm old corrupted non-bip70 invoices
fixes #6345
2020-07-08 00:57:23 +02:00
SomberNight
9cd79ec2e5 WalletDB: raise different exc if cannot parse given file
closes #6292
2020-06-27 16:03:03 +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
SomberNight
d5f368c584 LN invoices: support msat precision
fixes #6250
2020-06-22 22:48:13 +02:00
ThomasV
3874f7ec77 swaps: use StoredObject to store data 2020-06-18 14:28:40 +02:00
SomberNight
43892dd61a invoices: fix #6233 2020-06-14 03:39:35 +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
ThomasV
8f41aeb783 Replace wallet backup with channel backups
- channels can be backed up individually
 - backups are added to lnwatcher
 - AbstractChannel ancestor class
2020-04-10 14:45:23 +02:00
ThomasV
f3995350e8 localconfig: rename seed to channel_seed 2020-04-06 16:53:48 +02:00
ThomasV
0ea21c59d2 Save channel seed in localconfig 2020-04-04 13:28:19 +02:00
SomberNight
7ac1cace7a wallet_db.clear_history: now clears prevouts_by_scripthash too
(which is the logical thing to do, as it too will be rebuilt as part of
the history, and the parts of it that might not be present after the
rebuild is exactly what a call to "clear_history" is supposed to get rid of)
2020-03-27 02:28:43 +01:00
SomberNight
01207316aa storage upgrade: move "htlc_minimum_msat" to base channel config 2020-03-26 09:05:04 +01:00
SomberNight
ea0981ebeb lnutil.UpdateAddHtlc: use attrs instead of old-style namedtuple 2020-03-17 20:31:11 +01:00
ThomasV
444610452e wallet_db: encapsulate type conversions with attr.s converter 2020-03-17 11:04:49 +01:00
SomberNight
bf4b2a15a6 wallet_db: fix _convert_version_25 (bip70 expiration) 2020-03-05 17:15:09 +01:00
SomberNight
02fcc6f570 wallet_db.get_transaction: tolerate if tx_hash is None
Traceback (most recent call last):
  File "...\electrum\electrum\gui\qt\main_window.py", line 1503, in do_pay
    self.do_pay_invoice(invoice)
  File "...\electrum\electrum\gui\qt\main_window.py", line 1516, in do_pay_invoice
    self.pay_onchain_dialog(self.get_coins(), outputs)
  File "...\electrum\electrum\gui\qt\main_window.py", line 1570, in pay_onchain_dialog
    self.preview_tx_dialog(make_tx=make_tx,
  File "...\electrum\electrum\gui\qt\main_window.py", line 1574, in preview_tx_dialog
    d = PreviewTxDialog(make_tx=make_tx, external_keypairs=external_keypairs,
  File "...\electrum\electrum\gui\qt\transaction_dialog.py", line 654, in __init__
    self.update()
  File "...\electrum\electrum\gui\qt\transaction_dialog.py", line 392, in update
    tx_details = self.wallet.get_tx_info(self.tx)
  File "...\electrum\electrum\wallet.py", line 486, in get_tx_info
    tx_we_already_have_in_db = self.db.get_transaction(tx_hash)
  File "...\electrum\electrum\json_db.py", line 44, in wrapper
    return func(self, *args, **kwargs)
  File "...\electrum\electrum\wallet_db.py", line 822, in get_transaction
    assert isinstance(tx_hash, str)
AssertionError

Traceback (most recent call last):
  File "...\electrum\electrum\gui\qt\confirm_tx_dialog.py", line 65, in timer_actions
    self.update()
  File "...\electrum\electrum\gui\qt\transaction_dialog.py", line 392, in update
    tx_details = self.wallet.get_tx_info(self.tx)
  File "...\electrum\electrum\wallet.py", line 486, in get_tx_info
    tx_we_already_have_in_db = self.db.get_transaction(tx_hash)
  File "...\electrum\electrum\json_db.py", line 44, in wrapper
    return func(self, *args, **kwargs)
  File "...\electrum\electrum\wallet_db.py", line 822, in get_transaction
    if tx_hash is None:
AssertionError
2020-02-28 20:23:50 +01:00
SomberNight
88658f9c2c WalletDB: add type hints, and also corresponding asserts for sanity 2020-02-24 18:26:49 +01:00