1
0

193 Commits

Author SHA1 Message Date
SomberNight
c2e8188568 tests: test_network: add more header chain resolution test cases 2025-06-09 20:31:05 +00:00
SomberNight
eb69b6b516 interface: _search_headers_backwards: start at small delta
- interface.tip is the server's tip.
- consider scenario:
  - client has chain len 800_000, is up to date
  - client goes offline
  - suddenly there is a short reorg
      e.g. blocks 799_998, 799_999, 800_000 are reorged
  - client was offline for long time, finally comes back online again
  - server tip is 1_000_000, tip_header does not connect to client's local chain
  - PREVIOUSLY before commit, client would start backwards search
    - first it asks for header 800_001, which does not connect
    - then client asks for header ~600k, which checks
    - client will do long binary search to find the forkpoint
  - AFTER commit, client starts backwards search
    - first it asks for header 800_001, which does not connect
    - then client asks for header 799_999, etc
- that is, previously, on average, client did a short backwards search, followed by a long binary search
- now, on average, client does a longer backwards search, followed by a shorter binary search
  - this works much nicer with the headers_cache
  (- and thomasv said the old behaviour was not intentional)
2025-06-09 19:34:37 +00:00
SomberNight
02c6e118f0 tests: test_network: intro MockBlockchain. rewrite tests to use it.
interface.py no longer has knowledge about mocking! :P
2025-06-09 19:34:34 +00:00
SomberNight
cb1789a59c tests: test_network: try to explain test cases
no functional changes
2025-06-09 17:57:36 +00:00
SomberNight
09e412baf8 tests: enable verbose stderr logging
note: print() statements and stderr logging don't have a consistent printing order.
Either can buffer log lines and flush them later, and the buffers are independent.
2025-06-09 17:40:27 +00:00
SomberNight
ffb12b2833 tests: test_network: shorten lines 2025-06-09 17:22:49 +00:00
SomberNight
9016c36df0 tests: test_network.py: rm test_fork_conflict, no longer applicable
Just prior to this commit, test_fork_conflict and test_fork_noconflict were essentially identical copies.
The only diff was that test_fork_conflict set the global blockchain.blockchains,
but this was not even affecting its behaviour anymore.

Originally when this test was added, we had the concept of chain fork conflicting with each other:
we could not handle three-way chain-splits. As in, there could only be a single fork forking away
from the main chain at any given height.
see 7221fb3231

However, this restriction was removed and generalised later:
141ff99580
After which the "test_fork_conflict" test did not make sense anymore.
2025-06-09 15:46:02 +00:00
SomberNight
dbb9673139 interface: faster chain resolution: add headers_cache
We try to predict the next headers the interface will ask for,
and request them ahead of time, to be kept in the headers_cache.

This saves network latency/round-trips, for a bit more memory usage
and in some cases for more bandwidth.
Note that due to PaddedRSTransport.WAIT_FOR_BUFFER_GROWTH_SECONDS,
latency saved here can be longer than "real" network latency.

This speeds up
- binary search greatly,
- backwards search to a small degree
  (although not that much as its algorithm should be changed a bit to make it cache-friendly)
- catch-up greatly, if it's <10 blocks behind

What remains is to speed up catch-up in case we are behind by many thousands of block.
That behaviour is left unchanged here. The issue there is that we request chunks sequentially.
So e.g. 1 chunk (2016 blocks) per 1 second.
2025-06-09 15:36:04 +00:00
SomberNight
27599ac537 interface: small clean-up. intro ChainResolutionMode.
- type hints
- minor API changes
- no functional changes
2025-06-06 16:42:15 +00:00
ThomasV
1bf1de36cb txbatcher:
- add base_tx to wallet before broadcasting
 - remove base_tx in find_base_tx, it is local
 - add unit test in test_tx_batcher
2025-06-06 10:16:32 +02:00
ThomasV
8019ceb568 test_daemon: add test the wallet can be loaded by basename 2025-06-05 09:08:53 +02:00
ThomasV
37914d5af0 cmdline: use 'wallet_path' argument to pass wallet_path 2025-06-05 09:06:29 +02:00
SomberNight
3e4601c61d base64.b64decode: always set validate=True
Notably verifymessage and decrypt(message) were silently ignoring trailing garbage
or inserted non-base64 characters present in signatures/ciphertext.
(both the CLI commands and in the GUI)
I think it is much cleaner and preferable to treat such signatures/ciphertext as invalid.

In fact I find it surprising that base64.b64decode(validate=False) is the default.
Perhaps we should create a helper function for it that set validate=True and use that.
2025-06-03 18:58:05 +00:00
ThomasV
c13932452a test_lnpeer: add mock get_invoice method 2025-06-02 16:27:24 +02:00
ThomasV
9e225d1269 Replace config GUI_LAST_WALLET with CURRENT_WALLET
- CURRENT_WALLET is set when a single wallet is loaded in memory, and it
   remains set after Electrum stops running.
 - If several wallets are loaded at the same time, CURRENT_WALLET is unset,
   and RPCs must specify the wallet explicitly (using --wallet for the CLI)
 - The fallback to 'default_wallet' essentially only applies when
   creating a new wallet file
2025-06-02 14:05:53 +02:00
ThomasV
a23f370a43 follow-up ae7a1073cf
(todo: move these methods into lnworker)
2025-06-01 14:03:29 +02:00
ThomasV
40de52e829 regtest: make test_fw_fail morer reliable 2025-06-01 13:42:26 +02:00
ThomasV
ae7a1073cf Merge pull request #9685 from f321x/hold_invoice_cli
cli: add hold invoice cli functionality
2025-06-01 12:03:46 +02:00
ThomasV
43ca469774 Merge pull request #9555 from tianzedavid/master
chore: fix some typos
2025-05-30 14:36:12 +02:00
ThomasV
f0930ffc1d Merge pull request #9839 from SomberNight/202505_transaction_verify_sig_2
transaction: add method verify_sig_for_txin
2025-05-30 14:32:27 +02:00
ThomasV
e580373c82 test_redeem_offered_htlcs: reduce bob's target because they might send anchor output sweeping tx 2025-05-29 19:27:06 +02:00
SomberNight
db759765d6 adb.get_tx_height: allow future txs to be partially signed
If the full tx is missing, we should force mempool/confirmed txs to be LOCAL height,
however future txs should not be forced to LOCAL, they should remain FUTURE.

follow-up 197933debf
2025-05-27 18:19:01 +00:00
SomberNight
36d46ea2c1 tests: regtest.extract_preimage: nicer error msg in some failure cases
also rm an incorrect comment from overly-eager copy-paste
2025-05-26 16:53:17 +00:00
ThomasV
b0131c96f0 wallet.bump_fee: do not change nsequence of already existing inputs
Fixes tx rejection by network if the original tx has a csv:
> non-mandatory-script-verify-flag (Locktime requirement not satisfied)

Also add unit test
2025-05-26 14:52:37 +02:00
ThomasV
58480a69db TxBatcher: store fee policy names instead of fee descriptors
This allows to change the fee policy of batches dynamically.
Config.fee_policy is a mapping between policy names and descriptors.
2025-05-26 13:30:25 +02:00
ThomasV
25dabf3105 txbatcher: if we raise NotEnoughFunds, remove
the largest output from the current tx and retry

In the unit test, this results in waiting until the current tx is mined.
2025-05-23 17:11:56 +02:00
Sander van Grieken
caef77d45d tests: also test for RFC1918 IPv4 and IPv4-in-IPv6 and IPv6 link-local addresses 2025-05-22 11:02:46 +02:00
ThomasV
8d5d330b07 Merge pull request #9243 from accumulator/qml_oneserver
qt,qml: show option for single server in ServerConfig
2025-05-21 12:04:56 +02:00
accumulator
705f927899 qt: show option for single server in network dialog 2025-05-21 10:32:18 +02:00
f321x
cfdaafdd52 fix: suggest_splits exclude single channel splits 2025-05-20 17:34:48 +02:00
ThomasV
d1917b2951 Merge pull request #9837 from spesmilo/htlc_slots_left
pass number of htlc_slots_left to suggest_splits
2025-05-20 12:55:45 +02:00
ThomasV
b432a1406a lnchannel: apply stricter max_htlc_value_in_flight rules for receiving
Otherwise we create invoices that eclair cannot route to us
2025-05-20 12:44:14 +02:00
f321x
e433b8d5bf explicitly test the htlc slot limit in TestMppSplit 2025-05-20 12:26:21 +02:00
SomberNight
0508625afc transaction: add method verify_sig_for_txin
This new `Transaction.verify_sig_for_txin` function is an instance method of `Transaction` instead of `PartialTransaction`.
It takes a complete txin, a pubkey and a signature, and verifies the signature.

- `get_preimage_script` is renamed to `get_scriptcode_for_sighash` and now effectively has two implementations:
  - the old impl became `PartialTxInput.get_scriptcode_for_sighash`
    - this assumes we are the ones constructing a spending txin and can have knowledge beyond what will be revealed onchain
  - the new impl is in the base class, `TxInput.get_scriptcode_for_sighash`
    - this assumes the txin is already "complete", and mimics a consensus-verifier by extracting the required fields
      from the already complete witness/scriptSig and the scriptpubkey of the funding utxo
- `serialize_preimage` now does not require a PartialTransaction, it also works on the base class Transaction

-----

I intend to use this for debugging only atm: I noticed TxBatcher sometimes creates invalid signatures by seeing
that bitcoind rejects txs with `mandatory-script-verify-flag-failed (Signature must be zero for failed CHECK(MULTI)SIG operation)`.
However the txs in question have multiple txins, with some txins containing multiple signatures, and bitcoind does not tell us
which txin/signature is invalid. Knowing which signature is invalid would be a start, but I can now add some temp debug logging
to `serialize_preimage` to compare the message being signed with the message being verified.

As can be seen from the tests, the signature and the pubkey needs to be manually extracted from the txin to be verified:
we still don't have a script interpreter so we don't have logic to "verify a txin". However this new code adds logic
to verify a signature for a txin/pubkey combo (which is a small part of an interpreter/verifier).
2025-05-18 15:20:19 +00:00
ThomasV
a66439eea5 CLI: add preimage to get_invoice
This should make regtest extract_preimage more reliable
2025-05-18 15:25:06 +02:00
ThomasV
4a17d5a316 pass number of htlc_slots_left to suggest_splits 2025-05-17 15:50:03 +02:00
Sander van Grieken
c3f0993e53 test_lnchannel: add single_payment testcase for TestAvailableToSpend 2025-05-16 12:29:00 +02:00
SomberNight
6320597f2c regtests: rm sleep from "swapserver_forceclose" test
less reliance on timing
(OTOH it hardcodes the output index of the commitment tx... meh)
2025-05-15 19:50:16 +00:00
SomberNight
f3551f3c25 commands: add cmd wait_for_sync 2025-05-15 19:42:34 +00:00
SomberNight
61283fe18b adb: (trivial) receive_tx_callback: make tx_height param kw-only 2025-05-15 19:09:37 +00:00
ThomasV
6500788328 Merge pull request #9710 from f321x/dont_delete_config_on_syntax_error
config: Raise instead of overwriting the config file on syntax error
2025-05-15 17:24:35 +02:00
f321x
8870838834 raise instead of overwriting the config file on syntax error 2025-05-15 17:21:16 +02:00
ghost43
79a54c1578 Merge pull request #9826 from f321x/fix_fee_disagreement_ln
fix: reduce update_fee target for anchor channels
2025-05-15 13:30:11 +00:00
ThomasV
93e7de20e9 Merge pull request #9753 from f321x/debug_ln_payment_failure
ln: don't exclude single part configs for too small payments
2025-05-15 13:25:00 +02:00
f321x
e8171ca7c6 suggest_splits: don't exclude single part configs for too small multi
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.
2025-05-15 10:26:33 +02:00
f321x
61874e9fe7 fix: reduce update_fee target for anchor channels
the update_fee logic for lightning channels was not adapted to anchor
channels causing us to send update_fee with a eta target of 2 blocks.
This causes force closes when there are mempool spikes as the fees we
try to update to are a lot higher than e.g. eclair uses. Eclair will
force close if our fee is 10x > than their fee.
2025-05-14 18:01:44 +02:00
SomberNight
44f3444795 lnworker: make "preimages" dict private
I want to hook into lnworker.save_preimage (not done yet).
Other modules should not put preimages into the dict directly.
2025-05-14 13:23:02 +00:00
ThomasV
660ffa2b8f fix test_txbatcher (follow-up 6e3f173a71) 2025-05-13 09:09:35 +02:00
ThomasV
6e3f173a71 SweepInfo: define csv_delay as property 2025-05-13 08:50:33 +02:00
ThomasV
0607a406ce Qt: add closing warning if we have an unconfirmed local commitment tx with htlcs
add htlc direction (offered, received) to the htlc sweep_info name
regtest: add test_reedeem_received_htlcs
2025-05-12 15:48:20 +02:00