part configs
I noticed certain ln payments become very unreliable. These payments are ~21k sat, from gossip to gossip sender, with direct, unannounced channel.
Due to the recent fix https://github.com/spesmilo/electrum/pull/9723 `LNPathFinder.get_shortest_path_hops()` will not use channels for the last hop of a route anymore that aren't also passed to it in `my_sending_channels`:
```python
if edge_startnode == nodeA and my_sending_channels: # payment outgoing, on our channel
if edge_channel_id not in my_sending_channels:
continue
```
Conceptually this makes sense as we only want to send through `my_sending_channels`, however if the only channel between us and the receiver is a direct channel that we got from the r_tag and it's not passed in `my_sending_channel` it's not able to construct a route now.
Previously this type of payment worked as `get_shortest_path_hops()` knew of the direct channel between us and `nodeB` from the invoices r_tag and then just used this channel as the route, even though it was (often) not contained in `my_sending_channels`.
`my_sending_channels`, passed in `LNWallet.create_routes_for_payment()` is either a single channel or all our channels, depending on `is_multichan_mpp`:
```python
for sc in split_configurations:
is_multichan_mpp = len(sc.config.items()) > 1
```
This causes the unreliable, random behavior as `LNWallet.suggest_splits()` is supposed to `exclude_single_part_payments` if the amount is > `MPP_SPLIT_PART_MINAMT_SAT` (5000 sat).
As `mpp_split.py suggest_splits()` is selecting channels randomly, and then removes single part configs, it sometimes doesn't return a single configuration, as it removes single part splits, and also removes multi part splits if a part is below 10 000 sat:
```python
if target_parts > 1 and config.is_any_amount_smaller_than_min_part_size():
continue
```
This will result in a fallback to allow single part payments:
```python
split_configurations = get_splits()
if not split_configurations and exclude_single_part_payments:
exclude_single_part_payments = False
split_configurations = get_splits()
```
Then the payment works as all our channels are passed as `my_sending_channels` to `LNWallet.create_routes_for_payment()`.
However sometimes this fallback doesn't happen, because a few mpp configurations found in the first iteration of `suggest_splits` have been kept, e.g. [10500, 10500], but at the same time most others have been removed as they crossed the limit, e.g. [11001, 9999], (which happens sometimes with payments ~20k sat), this makes `suggest_splits` return very few usable channels/configurations (sometimes just one or two, even with way more available channels).
This makes payments in this range unreliable as we do not retry to generate new split configurations if the following path finding fails with `NoPathFound()`, and there is no single part configuration that allows the path finding to access all channels. Also this does not only affect direct channel payments, but all gossip payments in this amount range.
There seem to be multiple ways to fix this, i think one simple approach is to just disable `exclude_single_part_payments` if the splitting loop already begins to sort out configs on the second iteration (the first split), as this indicates that the amount may be too small to split within the given limits, and prevents the issue of having only few valid splits returned and not going into the fallback. However this also results in increased usage of single part payments.
the edit label button did crash the application because get_string
returned bytes instead of a string. The delete button was not
implemented but shown in the tui.
if payment amount is not set and the user tried to pay, the application
would crash. This shows a message instead. Also uses show_message
instead of show_error, as show_error doesn't exist.
37.23 | E | txbatcher.TxBatch | TxBatch error: AttributeError("'TxOutput' object has no attribute 'is_change'")
Traceback (most recent call last):
File "/opt/electrum/electrum/txbatcher.py", line 248, in run
await self.run_iteration()
File "/opt/electrum/electrum/txbatcher.py", line 379, in run_iteration
base_tx = self.find_base_tx()
File "/opt/electrum/electrum/txbatcher.py", line 369, in find_base_tx
self._new_base_tx(tx)
File "/opt/electrum/electrum/json_db.py", line 48, in wrapper
return func(self, *args, **kwargs)
File "/opt/electrum/electrum/txbatcher.py", line 518, in _new_base_tx
if tx.has_change():
File "/opt/electrum/electrum/transaction.py", line 1276, in has_change
return len(self.get_change_outputs()) > 0
File "/opt/electrum/electrum/transaction.py", line 1273, in get_change_outputs
return [o for o in self._outputs if o.is_change]
File "/opt/electrum/electrum/transaction.py", line 1273, in <listcomp>
return [o for o in self._outputs if o.is_change]
AttributeError: 'TxOutput' object has no attribute 'is_change'
There was no ability to read qr codes contained in image files. This
could lead to confusion in some contexts, as `on_file_input()` of
ScanQRTextEdit will read the whole content of the file (instead of
looking for qr codes). The revealer plugin for example generates png
files containing qr codes and uses the `ScanQRTextEdit` to get user
input, for the user it would seem logical to click on 'Read from file'
to load the generated file, however this will result in the wrong data
being loaded. Having the option to explicitly load a QR from file makes
this clear. Also it seems useful, especially considering reading QR from
screenshots doesn't work on wayland.
store all plugin data by plugin name in a root dictionary `plugin_data`
inside the wallet db so that plugin data can get deleted again.
Prunes the data of plugins from the wallet db on wallet stop if the
plugin is not installed anymore.
- if password is needed, await future and request it from GUI
- run asyncio task for each TxBatch, so that batches can
request the password concurrently