1
0
Commit Graph

169 Commits

Author SHA1 Message Date
ThomasV
5e09a416a7 address_synchronizer: save stored_height on each block 2023-08-27 11:57:50 +02:00
SomberNight
703ec09355 addr_sync: expand docstring for get_tx_fee 2023-06-13 00:24:56 +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
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
6ac3f84095 wallet/lnworker/etc: add sanity checks to start_network methods
related: https://github.com/spesmilo/electrum/issues/8301
2023-04-17 16:56:57 +00:00
SomberNight
b81508cfc0 qml: fix refresh bug in history, for local->unconfirmed tx transition
Previously if a local tx got broadcast, it was still displayed as local
in the history until it got mined (or some other action forced a full refresh).
2023-04-05 13:09:51 +00:00
SomberNight
e748345be0 addr_sync: change return type of get_address_history to dict from list 2023-04-05 13:09:47 +00:00
SomberNight
db4943ff86 wallet.get_full_history: more consistent sort order
before:
```
>>> [print(wallet.get_tx_status(txid, wallet.adb.get_tx_height(txid))) for txid in list(wallet.get_full_history())[-10:]]
(7, '2023-04-04 16:13')
(7, '2023-04-04 16:13')
(7, '2023-04-04 16:13')
(7, '2023-04-04 16:13')
(0, 'Unconfirmed [20. sat/b, 0.00 MB]')
(2, 'in 2 blocks')
(3, 'Local [180.4 sat/b]')
(3, 'Local [180.2 sat/b]')
(2, 'in 2016 blocks')
(0, 'Unconfirmed [180. sat/b, 0.00 MB]')
```

after:
```
>>> [print(wallet.get_tx_status(txid, wallet.adb.get_tx_height(txid))) for txid in list(wallet.get_full_history())[-10:]]
(7, '2023-04-04 16:13')
(7, '2023-04-04 16:13')
(7, '2023-04-04 16:13')
(7, '2023-04-04 16:13')
(0, 'Unconfirmed [20. sat/b, 0.00 MB]')
(0, 'Unconfirmed [180. sat/b, 0.00 MB]')
(2, 'in 2016 blocks')
(2, 'in 2 blocks')
(3, 'Local [180.4 sat/b]')
(3, 'Local [180.2 sat/b]')
```
2023-04-04 18:32:53 +00:00
SomberNight
f0e89b3ef6 addr_sync: migrate usages of get_txpos to get_tx_height
the return value of get_txpos is fine-tuned for sorting... other uses are highly questionable.
2023-04-04 17:49:46 +00:00
SomberNight
f8f0af4a2f qml: history: add some support for future txs
- they are now distinguished from local by the status text "in %d blocks"
- this status text needs updating occasionally: on new blocks,
  and some lnwatcher interactions, hence new event: "adb_set_future_tx"
2023-04-04 17:39:58 +00:00
SomberNight
9097d5e43d addr_sync.set_future_tx: clarify wanted_height off-by-one semantics 2023-04-04 13:55:12 +00:00
SomberNight
446879ade0 lnwatcher.maybe_redeem: wanted_height should always be absolute
previously, if prev_height.height was <= 0, lnwatcher was calling adb.set_future_tx()
with weird wanted_height values (with ~sweep_info.csv_delay)
2023-04-04 13:37:10 +00:00
ThomasV
54bb42f82c adb: take locks in get_balance. fixes #8200 2023-04-01 10:37:38 +02:00
SomberNight
81772faf6c wallet: add_input_info to no longer do network requests
- wallet.add_input_info() previously had a fallback to download parent
  prev txs from the network (after a lookup in wallet.db failed).
  wallet.add_input_info() is not async, so the network request cannot
  be done cleanly there and was really just a hack.
- tx.add_info_from_wallet() calls wallet.add_input_info() on each txin,
  in which case these network requests were done sequentially, not concurrently
- the network part of wallet.add_input_info() is now split out into new method:
  txin.add_info_from_network()
- in addition to tx.add_info_from_wallet(), there is now also tx.add_info_from_network()
  - callers of old tx.add_info_from_wallet() should now called either
    - tx.add_info_from_wallet(), then tx.add_info_from_network(), preferably in that order
    - tx.add_info_from_wallet() alone is sufficient if the tx is complete,
      or typically when not in a signing context
- callers of wallet.bump_fee and wallet.dscancel are now expected to have already
  called tx.add_info_from_network(), as it cannot be done in a non-async context
  (but for the common case of all-inputs-are-ismine, bump_fee/dscancel should work regardless)
- PartialTxInput.utxo was moved to the baseclass, TxInput.utxo
2023-03-12 00:21:57 +00:00
SomberNight
7584ba00ce wallet: kill negative conf numbers for TxMinedInfo
fixes https://github.com/spesmilo/electrum/issues/8240

#8240 was triggering an AssertionError in wallet.get_invoice_status,
as code there was assuming conf >= 0. To trigger, force-close
a LN channel, and while the sweep is waiting on the CSV, try to
make a payment in the Send tab to the ismine change address used
for the sweep in the future_tx. (order of events can also be reversed)
2023-03-09 14:59:08 +00:00
ThomasV
27ce9d88c3 follow-up 2ed71579c3: remove wrong assert 2023-03-04 09:04:50 +01:00
ThomasV
2ed71579c3 privacy analysis: detect address reuse
add tx position to get_addr_io
2023-03-04 08:53:49 +01:00
ThomasV
e4273e5ab9 utxo privacy analysis:
- add a new event, 'adb_removed_tx'
 - new wallet method: get_tx_parents
 - number of parents is shown in coins tab
 - detailed list of parents is shown in dialog
2023-02-25 11:46:47 +01:00
SomberNight
90f1279d9a addr_sync: (trivial) don't use private utxo._is_coinbase_output 2023-02-08 23:32:28 +00:00
SomberNight
7d42676785 qt tx dialog: make scid and addr texts clickable in IO fields
based on:
7eea0b6dae
52d845017c
2023-02-03 14:49:01 +00:00
ThomasV
7625b4e63b follow-up d6febb5c12 2023-01-26 11:13:35 +01:00
ThomasV
d6febb5c12 Display mined tx outputs as ShortIDs instead of full transaction outpoints.
ShortIDs were originally designed for lightning channels, and are now
understood by some block explorers.

This allows to remove one column in the UTXO tab (height is redundant).

In the transaction dialog, the space saving ensures that all inputs fit
into one line (it was not the case previously with p2wsh addresses).
For clarity and consistency, the ShortID is displayed for both inputs
and outputs in the transaction dialog.
2023-01-26 10:48:28 +01:00
SomberNight
29a0560f98 rework AddressSynchronizer.is_up_to_date
- AddressSynchronizer no longer has its own state re up_to_date,
  it defers to Synchronizer/Verifier instead
- Synchronizer is now tracking address sync states throughout their lifecycle:
  and Synchronizer.is_up_to_date() checks all states
- Synchronizer.add_queue (internal) is removed as it was redundant
- should fix wallet.is_up_to_date flickering during sync due to race

related:
dc6c481406
1c20a29a22
2022-12-21 15:23:11 +00:00
SomberNight
1c20a29a22 Revert "wallet.is_up_to_date: fix flickering during sync due to race"
This reverts commit dc6c481406 as it introduced its own issue:
while add_address was running on one thread, synchronizer._reset could be running on another,
and by the time the "enqueue" coro would run, it would use a new add_queue and
addr would not be in requested_addrs anymore...

```
I/w | wallet.Standard_Wallet.[test_segwit_2] | starting taskgroup.
I | lnworker.LNWallet.[test_segwit_2] | starting taskgroup.
E/i | interface.[testnet.qtornado.com:51002] | Exception in run: KeyError('tb1q3wmgf8n5eettnj50pzgnfrrpdpjmwn37x7nzsc5780kk4je9v4hspym8mu')
Traceback (most recent call last):
  File ".../electrum/electrum/util.py", line 1243, in wrapper
    return await func(*args, **kwargs)
  File ".../electrum/electrum/interface.py", line 506, in wrapper_func
    return await func(self, *args, **kwargs)
  File ".../electrum/electrum/interface.py", line 529, in run
    await self.open_session(ssl_context)
  File ".../electrum/electrum/interface.py", line 679, in open_session
    async with self.taskgroup as group:
  File ".../aiorpcX/aiorpcx/curio.py", line 304, in __aexit__
    await self.join()
  File ".../electrum/electrum/util.py", line 1339, in join
    task.result()
  File ".../electrum/electrum/synchronizer.py", line 80, in _run_tasks
    async with taskgroup as group:
  File ".../aiorpcX/aiorpcx/curio.py", line 304, in __aexit__
    await self.join()
  File ".../electrum/electrum/util.py", line 1339, in join
    task.result()
  File ".../electrum/electrum/synchronizer.py", line 127, in subscribe_to_address
    self.requested_addrs.remove(addr)
KeyError: 'tb1q3wmgf8n5eettnj50pzgnfrrpdpjmwn37x7nzsc5780kk4je9v4hspym8mu'
```
2022-12-20 16:15:24 +00:00
SomberNight
dc6c481406 wallet.is_up_to_date: fix flickering during sync due to race
AddressSynchronizer.add_address called synchronizer.add, which would only
schedule adding the addr to the Synchronizer in the next event loop iter.
If during that time, the synchronizer called adb.set_up_to_date(True),
the wallet would falsely believe and advertise itself as up_to_date
(as the wallet would see wallet.synchronize not creating new addresses,
and adb (via synchronizer) telling it is up_to_date).
Moments later, the synchronizer._add_address is finally executed and
up_to_date=False propagates out synchronizer->adb->wallet.
2022-12-20 13:58:02 +00:00
Sander van Grieken
21d1842b84 log if get_history fails sanity check 2022-12-03 11:09:51 +01:00
SomberNight
757ec53ea2 AddressSynchronizer: set diagnostic_name for better logs
fixes regression from 121d8732f1

in particular, this is needed for Synchronizer.diagnostic_name and SPV.diagnostic_name
2022-08-24 11:05:01 +00:00
ThomasV
60c493dc15 adb: trigger adb_added_tx event only if the transaction is new 2022-08-17 10:40:43 +02:00
ThomasV
dbf055de9a EventListener class to handle callbacks
and QtEventListener for Qt
2022-06-22 02:07:46 +02:00
ThomasV
6bef6fab86 adb: do not notify GUI about already known transactions 2022-06-13 10:53:43 +02:00
ThomasV
7d5125c935 lnwatcher: fix tx replacement and notifications
- revert the logic of do_breach_remedy to what it was
   before 0ca3d66d15,
   but now calling self.maybe_redeem unconditionally.
 - replace mempool transactions only if the fee increases
 - do not notify the GUI if a local tx is replaced
 - delete labels when replacing
2022-06-12 14:28:11 +02:00
SomberNight
29d8d8de26 wallet: (fix) cannot just piggyback on adb.is_up_to_date()
The wallet needs its own up_to_date logic:
- the adb being up_to_date means all its addresses are synced
- but an HD wallet might decide to roll the gap limit and generate new addresses
  - the adb does not know about this...
  - the wallet should be considered *not* up_to_date
- relatedly, it is now the wallet that decides to reset the network request counters

- note that wallet.main() was never cleaned up previously.
  - now wallet gets its own taskgroup, which is cleaned up in wallet.stop.

Follow-up to adb refactor: 121d8732f1
2022-06-10 18:55:55 +02:00
ThomasV
6e7ffa29ae Move address_is_old to AddressSynchronizer.
Cache local_height at that level instead of wallet.synchronize
2022-06-10 13:07:53 +02:00
ThomasV
0ca3d66d15 persist_lnwatcher: split try_redeem into two methods:
- maybe_add_redeem_tx
 - maybe_broadcast

Before this commit, local tx that are now persisted
are bot broadcast
2022-06-10 13:07:53 +02:00
ThomasV
c47057b484 Move get_wallet_delta to wallet class, because it requires wallet.is_mine
Do not call it in AddressSynchronizer.get_tx_fee
2022-06-10 13:07:53 +02:00
ThomasV
121d8732f1 Persist LNWatcher transactions in wallet file:
- separate AddressSynchronizer from Wallet and LNWatcher
 - the AddressSynchronizer class is referred to as 'adb' (address database)
 - Use callbacks to replace overloaded methods
2022-06-10 13:07:53 +02:00
SomberNight
2841cbeade addr_sync: also trigger address_history_changed when a tx is removed 2022-06-09 19:24:55 +02:00
SomberNight
d499dde811 addr_sync: get_balance change cache_key to have delimiters
re https://github.com/spesmilo/electrum/pull/7807/files#r870482609
2022-05-11 17:54:33 +02:00
ThomasV
1d498eeefc Change the semantics of get_balance:
It does not make sense to count change outputs in our unconfirmed balance,
because our balance will not be negatively affected if the transaction does
not get confirmed.

It is also incorrect to add signed values of get_addr_balance in order to compute
the balance over a domain. For example, this leads to incoming and outgoing
transactions cancelling out in our total unconfirmed balance.

This commit looks at the coins that are spent by a transaction. If those
coins belong to us and are confirmed, we do not count the transaction outputs
in our unconfirmed balance.

As a result, get_balance always returns positive values for unconfirmed balance.
2022-05-11 08:50:09 +02:00
ThomasV
dd43ccfda9 get_history: minor simplification 2022-05-07 18:46:28 +02:00
SomberNight
de724a214d asyncio: addr_sync: maybe fix "no current event loop in thread"
see https://github.com/spesmilo/electrum/issues/5376
crash report for electrum 4.2.1:
```
Traceback (most recent call last):
  File "/home/user/wspace/electrum/.buildozer/android/platform/build-arm64-v8a/build/python-installs/Electrum/kivy/base.py", line 347, in mainloop
  File "/home/user/wspace/electrum/.buildozer/android/platform/build-arm64-v8a/build/python-installs/Electrum/kivy/base.py", line 391, in idle
  File "/home/user/wspace/electrum/.buildozer/android/platform/build-arm64-v8a/build/python-installs/Electrum/kivy/base.py", line 342, in dispatch_input
  File "/home/user/wspace/electrum/.buildozer/android/platform/build-arm64-v8a/build/python-installs/Electrum/kivy/base.py", line 308, in post_dispatch_input
  File "kivy/_event.pyx", line 724, in kivy._event.EventDispatcher.dispatch
  File "/home/user/wspace/electrum/.buildozer/android/platform/build-arm64-v8a/build/python-installs/Electrum/kivy/uix/behaviors/button.py", line 179, in on_touch_up
  File "kivy/_event.pyx", line 720, in kivy._event.EventDispatcher.dispatch
  File "kivy/_event.pyx", line 1263, in kivy._event.EventObservers.dispatch
  File "kivy/_event.pyx", line 1147, in kivy._event.EventObservers._dispatch
  File "/home/user/wspace/electrum/.buildozer/android/platform/build-arm64-v8a/build/python-installs/Electrum/kivy/lang/builder.py", line 57, in custom_callback
  File "<string>", line 42, in <module>
  File "/home/user/wspace/electrum/.buildozer/android/app/electrum/gui/kivy/uix/dialogs/wallets.py", line 70, in cb
  File "/home/user/wspace/electrum/.buildozer/android/app/electrum/gui/kivy/main_window.py", line 710, in load_wallet_by_name
  File "/home/user/wspace/electrum/.buildozer/android/app/electrum/gui/kivy/main_window.py", line 728, in on_open_wallet
  File "/home/user/wspace/electrum/.buildozer/android/app/electrum/gui/kivy/main_window.py", line 691, in on_wizard_success
  File "/home/user/wspace/electrum/.buildozer/android/app/electrum/wallet.py", line 3267, in __new__
  File "/home/user/wspace/electrum/.buildozer/android/app/electrum/wallet.py", line 3111, in __init__
  File "/home/user/wspace/electrum/.buildozer/android/app/electrum/wallet.py", line 2904, in __init__
  File "/home/user/wspace/electrum/.buildozer/android/app/electrum/wallet.py", line 288, in __init__
  File "/home/user/wspace/electrum/.buildozer/android/app/electrum/address_synchronizer.py", line 97, in __init__
  File "/home/user/wspace/electrum/.buildozer/android/app/electrum/wallet.py", line 402, in load_and_cleanup
  File "/home/user/wspace/electrum/.buildozer/android/app/electrum/address_synchronizer.py", line 106, in load_and_cleanup
  File "/home/user/wspace/electrum/.buildozer/android/app/electrum/util.py", line 439, in <lambda>
  File "/home/user/wspace/electrum/.buildozer/android/app/electrum/util.py", line 435, in do_profile
  File "/home/user/wspace/electrum/.buildozer/android/app/electrum/address_synchronizer.py", line 432, in load_local_history
  File "/home/user/wspace/electrum/.buildozer/android/app/electrum/address_synchronizer.py", line 533, in _add_tx_to_local_history
  File "/home/user/wspace/electrum/.buildozer/android/app/electrum/address_synchronizer.py", line 548, in _mark_address_history_changed
  File "/home/user/wspace/electrum/.buildozer/android/platform/build-arm64-v8a/build/other_builds/python3/arm64-v8a__ndk_target_21/python3/Lib/asyncio/locks.py", line 260, in __init__
  File "/home/user/wspace/electrum/.buildozer/android/platform/build-arm64-v8a/build/other_builds/python3/arm64-v8a__ndk_target_21/python3/Lib/asyncio/events.py", line 639, in get_event_loop
RuntimeError: There is no current event loop in thread 'GUI'.
```
2022-04-26 20:24:15 +02:00
ThomasV
877a9f553b Merge pull request #7748 from spesmilo/confirm_reverse_swaps
Confirm reverse swaps
2022-04-09 10:41:02 +02:00
SomberNight
428dff90f8 address_sync: include verifier in sync_state progress indicator 2022-04-08 20:36:45 +02:00
SomberNight
30650c524c address_sync: "up_to_date" now waits for SPV 2022-04-08 20:35:23 +02:00
SomberNight
a05ef140d6 address_sync: split off unconfirmed_tx from unverified_tx 2022-04-08 20:34:45 +02:00
SomberNight
837fc1606c address_sync: change up_to_date to be private; no lock needed to read
After some consideration I am fairly certain there is no need to take
wallet.lock in `is_up_to_date()`. Any caller that might want some kind
of guarantees re the value returned by is_up_to_date() would need to
enforce them itself by e.g. taking wallet.lock around its critical code
block. That is, even if is_up_to_date() itself takes the lock, between
the call returning and the caller reading the value there could still
have been a race.
Also, the GUI was directly accessing the field already.
2022-04-08 20:33:13 +02:00
ThomasV
f01197b6b5 Reverse swaps: Wait until funding tx is confirmed
- override with allow_instant_swaps option (Qt)
2022-04-01 14:05:01 +02:00
ThomasV
1364e7538a bump fee of swap claim transactions
Note: This adds a new field, spent_txid, to PartialTxOutput
2022-03-30 13:44:10 +02:00
SomberNight
c9c094cfab requirements: bump min aiorpcx to 0.22.0
aiorpcx 0.20 changed the behaviour/API of TaskGroups.
When used as a context manager, TaskGroups no longer propagate
exceptions raised by their tasks. Instead, the calling code has
to explicitly check the results of tasks and decide whether to re-raise
any exceptions.
This is a significant change, and so this commit introduces "OldTaskGroup",
which should behave as the TaskGroup class of old aiorpcx. All existing
usages of TaskGroup are replaced with OldTaskGroup.

closes https://github.com/spesmilo/electrum/issues/7446
2022-02-15 18:22:44 +01:00
SomberNight
d94d443082 wallet: fire "request_status" event also when conf number changes 2021-07-11 16:57:01 +02:00