Commit Graph

573 Commits

Author SHA1 Message Date
Sander van Grieken
7b96a83350 wallet: add sighash check to class Abstract_Wallet
qml: use backend sighash check and add user confirmation path
qt: use backend sighash check and add user confirmation path
qml: include get_warning_for_risk_of_burning_coins_as_fees test in txdetails
qt: add warning icon to sighash warning
add sighash and fee checks to wallet.sign_transaction, making all warnings fatal unless ignore_warnings is set to True
tests: test sign_transaction on both code paths with ignore_warnings True and False,
raise specific exceptions TransactionPotentiallyDangerousException and TransactionDangerousException
2023-11-30 12:53:46 +01:00
SomberNight
6467db0b7d json_db: rename "_write" to sth more descriptive 2023-11-27 15:30:26 +00:00
SomberNight
7f64ecc4bd wallet.bump_fee: the glorious return of BumpFeeStrategy :D
gui/qt/rbf_dialog.py (old) lines 57-64 were implementing logic that should not be part of GUI code.
Case in point, gui/qml/qetxfinalizer.py (old) lines 511-513 duplicated half of that logic but not the other half.
That logic is now moved to wallet.get_bumpfee_strategies_for_tx().

More context: a user on irc got confused when using the qml gui. They were sending "max" and wanted to bump_fee.
The qml gui selected the "preserve_payment" strategy by default, using which there was no solution, and the user
did not notice that the strategy can be altered (via the "method" dropdown). The qt gui had logic to select
"decrease_payment" by default in such a case (which does find a solution to bump) but this logic was not
duplicated in the qml gui.
Instead of duplicating the logic, this commit moves it to shared lib code.
2023-11-20 18:55:43 +00:00
SomberNight
f1c63e2d51 commands: make payto/etc respect 'confirmed_only' config var
regression from 2f6d60c715

fixes https://github.com/spesmilo/electrum/issues/8693
2023-11-17 13:05:23 +00:00
Sander van Grieken
621a397b70 i18n: translate a few untranslated strings and avoid early translate for pr_tooltips and pr_expiration_values
fixes #8689
2023-11-14 12:07:49 +01:00
Sander van Grieken
e011bd235b qml: implement delete address for imported wallets, and fix address list on address/key add. 2023-11-10 09:30:56 +01:00
SomberNight
da8e6c2fbf wallet: check that multisig wallet does not have duplicate masterkeys
The wizard should technically disallows this at creation time,
but this second layer sanity check could not hurt.
Also, looks like the wizard check is not working properly atm
(regression from qt wizard refactor).
2023-10-30 17:22:08 +00:00
ThomasV
fac5153329 Merge pull request #8659 from accumulator/issue_8658
request: amount_msat is set to None in Request when creating request …
2023-10-25 17:55:39 +02:00
SomberNight
227e257444 (follow-up) wallet: add option to merge duplicate tx outputs 2023-10-24 14:41:39 +00:00
Sander van Grieken
420e584f4e request: amount_msat is set to None in Request when creating request and amount is 0 or undefined. 2023-10-24 13:48:00 +02:00
sha-265
ae8a546bb9 Merge multiple outputs to same address 2023-10-23 16:12:30 +00:00
SomberNight
57d2efc88d wallet: merge mktx and create_transaction 2023-10-10 17:45:26 +00:00
ThomasV
f4997c3771 follow-up 7576a99a0b 2023-10-10 19:41:37 +02:00
ThomasV
7576a99a0b wallet.unlock: raise exception if password is missing (follow-up 2e52b17a43) 2023-10-10 19:23:09 +02:00
SomberNight
65394c37d5 wallet.make_unsigned_transaction: add batch_rbf/send_change params
Don't side-effect config just to modify the next call of make_unsigned_transaction >.<
Cleaner to pass parameters.
2023-10-10 17:13:18 +00:00
ThomasV
3249e924d4 follow-up previous commit 2023-10-08 10:39:42 +02:00
ThomasV
2e52b17a43 CLI: replace the 'unlock' command with an option passed to load_wallet
Some use cases require the wallet to be unlocked at load time.
2023-10-08 10:21:01 +02:00
ThomasV
40eba6f780 submarine swaps: improve labels
- claim tx was incorrectly labeled
 - if we send tx change to a swap, display both labels
2023-10-05 15:41:04 +02:00
ThomasV
6de40321c5 rbf batching: make sure new feerate > old feerate
The previous lower bound did not ensure that, sometimes
resulting in tx rejection. Note, though, that BIP125 does
not explicitly state that the new feerate must be strictly
higher than the old feerate.
2023-10-04 11:57:26 +02:00
ThomasV
7ca89f56ee partial-writes using jsonpatch
- partial writes are append only.

 - StoredDict objects will append partial writes to the wallet
   file when items are added, replaced, removed.

 - Lists in the wallet file that have not been registered
   as StoredObject are converted to StoredList, which
   overloads append() and remove(). Those methods too will
   append partial writes to the wallet file.

 - Unlike the old jsonpatch branch, this branch does not support
   file encryption. Encrypted files always fully rewritten, even
   if the change before encryption is a partial write.
2023-09-24 12:24:09 +02:00
ThomasV
56e80c20d7 wallet_db upgrade: do not use '/' in StoredDict keys 2023-09-23 11:05:36 +02:00
ThomasV
68159b3ef6 walletDB: replace 'manual_upgrades' parameter with 'upgrade', with opposite semantics 2023-09-22 15:02:07 +02:00
ThomasV
b5bc5ff9ed Separate WalletDB from storage upgrades.
Make sure that WalletDB.data is always a StoredDict.
Perform db upgrades in a separate class, since they
operate on a dict object.
2023-09-22 15:02:06 +02:00
SomberNight
baa443295d wallet: add sanity check for storage encryption version
multisig wallet cannot have StorageEncryptionVersion.XPUB_PASSWORD
2023-09-20 17:28:18 +00:00
ThomasV
f8c2a38954 get_full_history: replace item if it has unique child
(follow-up 7eabbbc81f)

This may happen if we delete a local transaction.
2023-09-20 16:48:59 +02:00
ThomasV
7eabbbc81f Move history grouping logic from qt GUI to wallet.get_full_history()
Tx groups are now rendered similarly on all GUIs.
2023-09-16 15:39:32 +02:00
SomberNight
4c63d8729b add sanity checks we don't sign tx including dummy addr
Somewhat a follow-up to 649ce979ab.

This adds some safety belts so we don't accidentally sign a tx that
contains a dummy address.
Specifically we check that tx does not contain output for dummy addr:
- in wallet.sign_transaction
- in network.broadcast_transaction

The second one is perhaps redundant, but I think it does not hurt.
2023-09-16 04:36:08 +00:00
ThomasV
4e80ef818d Add unlock command to CLI (stores wallet password in memory) 2023-09-15 15:37:53 +02:00
ThomasV
d03c77837f Let the GUI compute the balance displayed in history.
Since Qt groups swap transactions, the displayed balance
was sometimes incorrect.
2023-09-14 15:58:58 +02:00
ThomasV
649ce979ab send tx change to lightning 2023-09-09 14:14:43 +02:00
ThomasV
b96cc82333 Make storage a field of db
This comes from the jsonpatch_new branch.
I rather have in master now, because it touches a lot of filese.
2023-08-18 08:08:31 +02:00
Sander van Grieken
f980bd97b5 payment_identifier: factor out bip21 functions to bip21.py to break cyclic dependencies,
parse bolt11 only once, store invoice internally instead of bolt11 string
add is_onchain method to indicate if payment identifier can be paid onchain
2023-07-08 12:18:37 +02:00
ThomasV
15eb765eac payment_identifiers:
- this separates GUI from core handling
 - the PaymentIdentifier class handles network requests
 - the GUI is agnostic about the type of PI
2023-06-28 16:49:28 +02:00
SomberNight
033ad0feb9 lnworker: fix rebalance_channels
fixes https://github.com/spesmilo/electrum/issues/8468
2023-06-04 03:07:06 +00:00
SomberNight
24980feab7 config: introduce ConfigVars
A new config API is introduced, and ~all of the codebase is adapted to it.
The old API is kept but mainly only for dynamic usage where its extra flexibility is needed.

Using examples, the old config API looked this:
```
>>> config.get("request_expiry", 86400)
604800
>>> config.set_key("request_expiry", 86400)
>>>
```

The new config API instead:
```
>>> config.WALLET_PAYREQ_EXPIRY_SECONDS
604800
>>> config.WALLET_PAYREQ_EXPIRY_SECONDS = 86400
>>>
```

The old API operated on arbitrary string keys, the new one uses
a static ~enum-like list of variables.

With the new API:
- there is a single centralised list of config variables, as opposed to
  these being scattered all over
- no more duplication of default values (in the getters)
- there is now some (minimal for now) type-validation/conversion for
  the config values

closes https://github.com/spesmilo/electrum/pull/5640
closes https://github.com/spesmilo/electrum/pull/5649

Note: there is yet a third API added here, for certain niche/abstract use-cases,
where we need a reference to the config variable itself.
It should only be used when needed:
```
>>> var = config.cv.WALLET_PAYREQ_EXPIRY_SECONDS
>>> var
<ConfigVarWithConfig key='request_expiry'>
>>> var.get()
604800
>>> var.set(3600)
>>> var.get_default_value()
86400
>>> var.is_set()
True
>>> var.is_modifiable()
True
```
2023-05-25 17:39:48 +00:00
SomberNight
68fb996d20 wallet_db version 52: break non-homogeneous multisig wallets
- case 1: in version 4.4.1, 4.4.2, the qml GUI wizard allowed creating multisig wallets with an old_mpk as cosigner.
- case 2: in version 4.4.0, 4.4.1, 4.4.2, the qml GUI wizard allowed creating multisig wallets with mixed xpub/Ypub/Zpub.

The corresponding missing input validation was a bug in the wizard, it was unintended behaviour. Validation was added in d2cf21fc2b. Note however that there might be users who created such wallet files.

Re case 1 wallet files: there is no version of Electrum that allows spending from such a wallet. Coins received at addresses are not burned, however it is technically challenging to spend them. (unless the multisig can spend without needing the old_mpk cosigner in the quorum).

Re case 2 wallet files: it is possible to create a corresponding spending wallet for such a multisig, however it is a bit tricky. The script type for the addresses in such a heterogeneous xpub wallet is based on the xpub_type of the first keystore. So e.g. given a wallet file [Yprv1, Zpub2] it will have sh(wsh()) scripts, and the cosigner should create a wallet file [Ypub1, Zprv2] (same order).

Technically case 2 wallet files could be "fixed" automatically by converting the xpub types as part of a wallet_db upgrade. However if the wallet files also contain seeds, those cannot be converted ("standard" vs "segwit" electrum seed).
Case 1 wallet files are not possible to "fix" automatically as the cosigner using the old_mpk is not bip32 based.

It is unclear if there are *any* users out there affected by this. I suspect for case 1 it is very likely there are none (not many people have pre-2.0 electrum seeds which were never supported as part of a multisig who would also now try to create a multisig using them); for case 2 however there might be.

This commit breaks both case 1 and case 2 wallets: these wallet files can no longer be opened in new Electrum, an error message is shown and the crash reporter opens. If any potential users opt to send crash reports, at least we will know they exist and can help them recover.
2023-05-11 14:26:11 +00:00
SomberNight
38ec72527f wallet.get_bolt11_invoice: handle request not having LN part
fixes https://github.com/spesmilo/electrum/issues/8402

To reproduce,
- create wallet from a zpub
- LN is disabled there by default
- create a receive request, which won't have a lightning part
- enable config var "bip21_lightning"
- enable LN
- existing request is now ~breaking receive tab
2023-05-07 00:39:06 +00:00
ThomasV
c0917e65af fix #8391: reintroduce recursion, limited to unconfirmed transactions
It would be better to have topological order, but this issue needs to
be fixed quickly.
2023-05-06 18:10:51 +02:00
SomberNight
1e55042830 wallet: set_frozen_state_of_{addresses,coins} to save_db() to disk
fixes https://github.com/spesmilo/electrum/issues/8389
2023-05-06 13:26:08 +00:00
SomberNight
9c47144418 qt: handle expected errors in DSCancelDialog
closes https://github.com/spesmilo/electrum/issues/8390
2023-05-05 16:06:16 +00:00
SomberNight
56fa832563 wallet.get_tx_parents: explicitly handle missing "from address"
(happened to work even without this)
2023-05-03 15:08:56 +00:00
SomberNight
a1bfea6121 wallet.get_tx_parents: fix: tx should not be its own uncle
```
  3.06 | I | w/wallet.Standard_Wallet.[default_wallet] | get_tx_parents() cp0. entered for txid='407d03126255cce62a1101075db906587bd492f512166119d3f87b8a1b013497'
  3.06 | I | w/wallet.Standard_Wallet.[default_wallet] | get_tx_parents() cp4.1. parents=['e2d915520f6d42273158a6fd08b38d812bd554aa906d3ed45d103757d45af2bb']
  3.06 | I | w/wallet.Standard_Wallet.[default_wallet] | get_tx_parents() cp4.2. uncles=[]
  3.06 | I | w/wallet.Standard_Wallet.[default_wallet] | get_tx_parents() cp2. populating cache... _txid='434808dab0c93715bb8b7ce85f73bffd0bdf7c1ba205fe0f704226646971e555'
  3.06 | I | w/wallet.Standard_Wallet.[default_wallet] | get_tx_parents() cp0. entered for txid='434808dab0c93715bb8b7ce85f73bffd0bdf7c1ba205fe0f704226646971e555'
  3.06 | I | w/wallet.Standard_Wallet.[default_wallet] | get_tx_parents() cp3.0. uncle_txid='434808dab0c93715bb8b7ce85f73bffd0bdf7c1ba205fe0f704226646971e555'
  3.06 | I | w/wallet.Standard_Wallet.[default_wallet] | get_tx_parents() cp3.1. reuse_height=-2 reuse_pos=-1
  3.06 | I | w/wallet.Standard_Wallet.[default_wallet] | get_tx_parents() cp3.2. my_height=1338 my_pos=1
  3.06 | I | w/wallet.Standard_Wallet.[default_wallet] | get_tx_parents() cp4.1. parents=['407d03126255cce62a1101075db906587bd492f512166119d3f87b8a1b013497']
  3.06 | I | w/wallet.Standard_Wallet.[default_wallet] | get_tx_parents() cp4.2. uncles=['434808dab0c93715bb8b7ce85f73bffd0bdf7c1ba205fe0f704226646971e555']
 40.82 | E | gui.qt.exception_window.Exception_Hook | exception caught by crash reporter
Traceback (most recent call last):
  File "/home/user/wspace/electrum/electrum/gui/qt/main_window.py", line 846, in timer_actions
    self.update_wallet()
  File "/home/user/wspace/electrum/electrum/gui/qt/main_window.py", line 1001, in update_wallet
    self.update_tabs()
  File "/home/user/wspace/electrum/electrum/gui/qt/main_window.py", line 1013, in update_tabs
    self.utxo_list.update()
  File "/home/user/wspace/electrum/electrum/util.py", line 470, in <lambda>
    return lambda *args, **kw_args: do_profile(args, kw_args)
  File "/home/user/wspace/electrum/electrum/util.py", line 465, in do_profile
    o = func(*args, **kw_args)
  File "/home/user/wspace/electrum/electrum/gui/qt/utxo_list.py", line 115, in update
    self.refresh_row(name, idx)
  File "/home/user/wspace/electrum/electrum/gui/qt/utxo_list.py", line 137, in refresh_row
    num_parents = self.wallet.get_num_parents(txid)
  File "/home/user/wspace/electrum/electrum/wallet.py", line 897, in get_num_parents
    self._num_parents[txid] = len(self.get_tx_parents(txid))
  File "/home/user/wspace/electrum/electrum/wallet.py", line 910, in get_tx_parents
    self.get_tx_parents(_txid)
  File "/home/user/wspace/electrum/electrum/wallet.py", line 938, in get_tx_parents
    p = self._tx_parents_cache[_txid]
KeyError: '434808dab0c93715bb8b7ce85f73bffd0bdf7c1ba205fe0f704226646971e555'
```
2023-05-03 15:06:37 +00:00
SomberNight
5512c7d905 wallet.get_tx_info: distinguish "future" tx from local in "status" str
closes https://github.com/spesmilo/electrum/issues/8379
2023-05-03 14:15:08 +00:00
ThomasV
8a25d59ba6 wallet: save num_parents of utxos in wallet file.
fixes #8361
2023-05-02 09:27:39 +02:00
ThomasV
6d392a67f9 wallet.get_tx_parents: populate cache regardless of self.is_up_to_date()
Fixes #8315
2023-05-02 09:11:21 +02:00
SomberNight
57ae933582 (trivial) add some type hints to wallet.get_tx_parents 2023-04-26 18:11:55 +00:00
ThomasV
8dca907891 get_tx_parent: populate cache in chronological order 2023-04-26 18:29:46 +02:00
SomberNight
ad5f95cb87 util.profiler: add "min_threshold" arg 2023-04-26 14:49:37 +00:00
SomberNight
bf41675d4c qml: invoice/request list: flip sort order: newest on top
to be consistent with the History, and with other GUIs

(the model is the easiest place to do it. QSortFilterProxyModel/etc looks overkill)
2023-04-24 15:33:10 +00:00
SomberNight
612d3493df fix flake8-bugbear B017
B017 `assertRaises(Exception)` and `pytest.raises(Exception)` should be considered evil. They can lead to your test passing even if the code being tested is never executed due to a typo. Assert for a more specific exception (builtin or custom), or use `assertRaisesRegex` (if using `assertRaises`), or add the `match` keyword argument (if using `pytest.raises`), or use the context manager form with a target.
2023-04-24 12:58:30 +00:00