exc triggered when switching from same server to same server:
```
9.43 | D | gui.qml.qenetwork | server_status updated: Connecting
9.43 | E | network | Exception in _run_new_interface: Exception('diagnostic name not yet available?')
Traceback (most recent call last):
File "/home/user/wspace/electrum/electrum/logging.py", line 241, in __get_logger_for_obj
diag_name = self.diagnostic_name()
File "/home/user/wspace/electrum/electrum/interface.py", line 555, in diagnostic_name
return self.server.net_addr_str()
AttributeError: 'str' object has no attribute 'net_addr_str'
The above exception was the direct cause of the following exception:
Traceback (most recent call last):
File "/home/user/wspace/electrum/electrum/util.py", line 1218, in wrapper
return await func(*args, **kwargs)
File "/home/user/wspace/electrum/electrum/network.py", line 986, in _run_new_interface
interface = Interface(network=self, server=server)
File "/home/user/wspace/electrum/electrum/interface.py", line 502, in __init__
Logger.__init__(self)
File "/home/user/wspace/electrum/electrum/logging.py", line 232, in __init__
self.logger = self.__get_logger_for_obj()
File "/home/user/wspace/electrum/electrum/logging.py", line 243, in __get_logger_for_obj
raise Exception("diagnostic name not yet available?") from e
Exception: diagnostic name not yet available?
```
- on my PC, with Tor Browser running (socks proxy on port 9150), detect_tor_socks_proxy took ~4.01 seconds
- this was because we probed port 9050, 2 sec timeout, 9051, 2 sec timeout, 9150, ~few ms to succeed
- instead we now probe all ports concurrently
- Wallet.make_unsigned_transaction takes a FeePolicy parameter
- fee sliders act on a FeePolicy instead of config
- different fee policies may be used for different purposes
- do not detect dust outputs in lnsweep, delegate that to lnwatcher
allow enable/disable proxy without nuking proxy mode, host and port (explicit enable_proxy config setting),
move tor probe from frontend to backend code, add probe buttons for Qt and QML
This avoids some false negatives for is_proxy_tor.
(previously we only set is_proxy_tor when the proxy settings were changed)
In particular, consider scenario:
- Tor browser not running
- user sets "localhost:9150" as proxy
- detection sets network.is_proxy_tor to False
- user starts Tor browser
- network, due to retries, finds proxy working and connects to some servers
- network.is_proxy_tor remains False
```
32.40 | 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/wizard/wallet.py", line 709, in <lambda>
button.clicked.connect(lambda: Bip39RecoveryDialog(self, get_account_xpub, on_account_select))
File "/home/user/wspace/electrum/electrum/gui/qt/bip39_recovery_dialog.py", line 40, in __init__
fut = asyncio.run_coroutine_threadsafe(coro, network.asyncio_loop)
AttributeError: 'NoneType' object has no attribute 'asyncio_loop'
```
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.
We should not show the untrusted text in the GUI...
With this change, we still log the text, but otherwise it should avoid
unintentionally showing it anywhere, as the original exception is
masked away.
related: https://github.com/spesmilo/electrum/issues/8599#issuecomment-1706775508
Example traceback (and the exc is then shown in main_window.on_error):
```
10.77 | D | n/network | got error from server for Network.listunspent_for_scripthash: <UntrustedServerReturnedError [DO NOT TRUST THIS MESSAGE] original_exception: "RPCError(0, 'heyheyhey')">
10.78 | E | gui.qt.main_window.[test_segwit_2] | on_error
Traceback (most recent call last):
File "...\electrum\electrum\network.py", line 898, in wrapper
return await func(self, *args, **kwargs)
File "...\electrum\electrum\network.py", line 1149, in listunspent_for_scripthash
return await self.interface.listunspent_for_scripthash(sh)
File "...\electrum\electrum\interface.py", line 1027, in listunspent_for_scripthash
raise aiorpcx.jsonrpc.RPCError(0, "heyheyhey")
aiorpcx.jsonrpc.RPCError: (0, 'heyheyhey')
The above exception was the direct cause of the following exception:
Traceback (most recent call last):
File "...\electrum\electrum\gui\qt\util.py", line 925, in run
result = task.task()
File "...\electrum\electrum\gui\qt\main_window.py", line 2505, in <lambda>
task = lambda: self.network.run_from_another_thread(
File "...\electrum\electrum\network.py", line 383, in run_from_another_thread
return fut.result(timeout)
File "...\Python310\lib\concurrent\futures\_base.py", line 458, in result
return self.__get_result()
File "...\Python310\lib\concurrent\futures\_base.py", line 403, in __get_result
raise self._exception
File "...\electrum\electrum\wallet.py", line 151, in sweep_preparations
async with OldTaskGroup() as group:
File "...\aiorpcX\aiorpcx\curio.py", line 304, in __aexit__
await self.join()
File "...\electrum\electrum\util.py", line 1316, in join
task.result()
File "...\electrum\electrum\wallet.py", line 142, in find_utxos_for_privkey
await _append_utxos_to_inputs(
File "...\electrum\electrum\wallet.py", line 129, in _append_utxos_to_inputs
u = await network.listunspent_for_scripthash(scripthash)
File "...\electrum\electrum\network.py", line 872, in make_reliable_wrapper
async with OldTaskGroup(wait=any) as group:
File "...\aiorpcX\aiorpcx\curio.py", line 304, in __aexit__
await self.join()
File "...\electrum\electrum\util.py", line 1327, in join
self.completed.result()
File "...\electrum\electrum\network.py", line 903, in wrapper
raise wrapped_exc from e
electrum.network.UntrustedServerReturnedError: The server returned an error.
```
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
```
local_watchtower.adb.start_network was getting called twice.
follow-up 6ac3f84095
```
20230418T014725.636141Z | ERROR | __main__ |
Traceback (most recent call last):
File "/home/user/wspace/electrum/./run_electrum", line 435, in main
handle_cmd(
File "/home/user/wspace/electrum/./run_electrum", line 469, in handle_cmd
d = daemon.Daemon(config, fd)
File "/home/user/wspace/electrum/electrum/util.py", line 462, in <lambda>
return lambda *args, **kw_args: do_profile(args, kw_args)
File "/home/user/wspace/electrum/electrum/util.py", line 458, in do_profile
o = func(*args, **kw_args)
File "/home/user/wspace/electrum/electrum/daemon.py", line 404, in __init__
self.network = Network(config, daemon=self)
File "/home/user/wspace/electrum/electrum/network.py", line 348, in __init__
self.local_watchtower.adb.start_network(self)
File "/home/user/wspace/electrum/electrum/address_synchronizer.py", line 185, in start_network
assert self.network is None, "already started"
AssertionError: already started
```