1
0
Commit Graph

340 Commits

Author SHA1 Message Date
f321x
c34efce984 lnchannel: allow deleting unfunded incoming channels
We tried to delete incoming channels that didn't get funded after
lnutil.CHANNEL_OPENING_TIMEOUT, however an assert prevented this:

```
  3.63 | E | lnwatcher.LNWatcher.[default_wallet-LNW] | Exception in check_onchain_situation: AssertionError()
Traceback (most recent call last):
  File "/home/user/code/electrum-fork/electrum/util.py", line 1233, in wrapper
    return await func(*args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/user/code/electrum-fork/electrum/lnwatcher.py", line 117, in check_onchain_situation
    await self.update_channel_state(
    ...<5 lines>...
        keep_watching=keep_watching)
  File "/home/user/code/electrum-fork/electrum/lnwatcher.py", line 135, in update_channel_state
    chan.update_onchain_state(
    ~~~~~~~~~~~~~~~~~~~~~~~~~^
        funding_txid=funding_txid,
        ^^^^^^^^^^^^^^^^^^^^^^^^^^
    ...<2 lines>...
        closing_height=closing_height,
        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
        keep_watching=keep_watching)
        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/user/code/electrum-fork/electrum/lnchannel.py", line 341, in update_onchain_state
    self.update_unfunded_state()
    ~~~~~~~~~~~~~~~~~~~~~~~~~~^^
  File "/home/user/code/electrum-fork/electrum/lnchannel.py", line 382, in update_unfunded_state
    self.lnworker.remove_channel(self.channel_id)
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^
  File "/home/user/code/electrum-fork/electrum/lnworker.py", line 3244, in remove_channel
    assert chan.can_be_deleted()
           ~~~~~~~~~~~~~~~~~~~^^
AssertionError
```
2025-12-10 13:20:32 +01:00
ghost43
f8fc2b63e3 Merge pull request #10271 from f321x/fix_save_payment_info
lightning: fix self payments (e.g. rebalance)
2025-12-05 17:19:39 +00:00
ThomasV
55cc27d27e Test JIT channels: check that lnpay success is true.
This test fails since 0f314d1dd9
2025-12-05 12:05:37 +01:00
ThomasV
40729aa0e5 test accounting_addresses: stop alice before requesting, because we need a new session.
(follow-up 9b72dc297b)
2025-12-05 11:31:27 +01:00
ThomasV
9b72dc297b lnwatcher: remove rearly return that breaks accounting_addresses
This reverts 6ffaa55.
Also, in regtests, add a check that fails if accounting_addresses are broken.
2025-12-04 10:26:01 +01:00
SomberNight
14fd85f935 json_db: fix StoredDict.__delitem__() to work similarly to .pop()
follow-up https://github.com/spesmilo/electrum/pull/10233 ("jsondb pointers")
2025-12-01 19:42:47 +00:00
SomberNight
afc87fea9a tests: json_db: add more asserts for clarity 2025-12-01 19:33:14 +00:00
f321x
923d48f9db lnworker: differentiate PaymentInfo by direction
Allows storing two different payment info of the same payment hash by
including the direction into the db key.
We create and store PaymentInfo for sending attempts and for requests (receiving),
if we try to pay ourself (e.g. through a channel rebalance) the checks
in `save_payment_info` would prevent this and throw an exception.
By storing the PaymentInfos of outgoing and incoming payments separately in
the db this collision is avoided and it makes it easier to reason about
which PaymentInfo belongs where.
2025-12-01 18:39:56 +01:00
f321x
af4dc24d87 lnworker: use config lightning fee for estimate
I was unable to do a "Max" amount submarine swap because the
`fee_estimate` method used by `LNWallet.num_sats_can_send()` uses a
hardcoded `fee_proportional_millionths` to estimate the fee for the
lightning payment.
When the actual fee determined later is higher
than the estimated fee the payment fails as the channel is unable to add
the htlc sum including the real fees as the amount exceeds the balance of
the channel.
Using the fees the maximum fees user has configured and estimate the
potential fee as inverse of PaymentFeeBudget is more
reliable/conservative as we definitely aren't going to pay more fees
than this amount.
2025-11-28 16:25:34 +01:00
f321x
59586d6f94 tests: lnpeer: add test_payment_with_malformed_onion
Adds a simple forwarding test where the receiver fails a malformed onion with
`update_fail_malformed_htlc`.
2025-11-27 17:58:51 +01:00
f321x
1fd5458b0e tests: lnpeer: test_dont_expire_htlcs
Adds unittest to test the dont_expire_htlcs logic
2025-11-27 17:58:47 +01:00
f321x
4f2e1b65f0 tests: test_lnpeer: add test_dont_settle_htlcs
Adds test for the dont_settle_htlcs functionality of lnworker used by
Just-In-Time channels.
2025-11-27 17:58:46 +01:00
f321x
abc469c846 lnworker: split dont_settle_htlcs
Splits `LNWallet.dont_settle_htlcs` into `LNWallet.dont_settle_htlcs`
and `LNWallet.dont_expire_htlcs`.

Registering a payment hash in dont_settle_htlcs will prevent it from
getting fulfilled if we have the preimage stored. The preimage will not
be released before the the payment hash gets removed from
dont_settle_htlcs. Htlcs can still get expired as usual or failed if no
preimage is known.
This is only used by Just-in-time channel openings.

Registering a payment hash in dont_expire_htlcs allows to overwrite the
minimum final cltv delta value after which htlcs would usually get
expired. This allows to delay expiry of htlcs or, if the value in the
dont_settle_htlcs dict is None, completely prevent expiry and let the
htlc get expired onchain.

Splitting this up in two different dicts makes it more explicit and
easier to reason about what they are actually doing.

 Please enter the commit message for your changes. Lines starting
2025-11-27 17:58:44 +01:00
f321x
b1e58450bd tests: test_lnpeer: add test_payment_bundle_with_hold_invoice
Adds test_payment_bundle_with_hold_invoice to simulate the use of a
payment bundle in which one invoice of the bundle needs to trigger a hold invoice
callback (similar to submarine swaps).
Also modifies the test helper _test_simple_payment() to compare the
results of all payment attempts instead of just returning after the
first (of multiple) payments raises its result causing the test to miss
if all payments were successful or not.
2025-11-27 17:58:43 +01:00
f321x
042557da9b tests: test_lnpeer: test_htlc_switch_iteration_benchmark
Benchmark how long a call to _run_htlc_switch_iteration takes with 10
trampoline mpp sets of 1 htlc each.
2025-11-27 17:58:40 +01:00
f321x
f56b13b610 tests: test_lnpeer: test_hold_invoice_set_doesnt_get_exp
Add test `test_hold_invoice_set_doesnt_get_expired` to test_lnpeer to
ensure a mpp set on which a hold invoice callback doesn't get expired
automatically if the cltv_abs falls below MIN_FINAL_CLTV_DELTA_ACCEPTED
as these sets should only get failed if the htlcs are safe to fail by
the target of the hold invoice callback (e.g. swap got refunded
successfully).
2025-11-27 17:58:38 +01:00
f321x
bb828097b3 tests: test_lnpeer: test compare trampoline onions
Adds test_forwarder_fails_for_inconsistent_trampoline_onions
which checks that a forwarder compares the trampoline onions of a mpp
set and fails the set if the onions are not similar.
In the test alice sends a mpp through bob with 2 htlcs, in one
trampoline onion amt_to_forward is off by 1 msat so bob fails the htlc
set instead of initiating the trampoline forwarding.
2025-11-27 17:58:34 +01:00
f321x
447d91d7b6 tests: lnpeer: test_trampoline_mpp_consolidation_forwarding_amount
Add sanity check that bob is not forwarding more sats to carol if than
he receives from alice. (he only forwards once and doesn't try to
forward multiple times).
This should get caught by asserts in lnworker/lnpeer, nevertheless it
seems to make sense to just add this test to prevent regressions of this
kind.
2025-11-27 17:57:26 +01:00
f321x
f35b353841 tests: lnpeer: test_mpp_cleanup_after_expiry
1. Alice sends two HTLCs to Bob, not reaching total_msat,
   and eventually they MPP_TIMEOUT
2. Bob fails both HTLCs
3. Alice then retries and sends HTLCs again to Bob, for the same RHASH,
   this time reaching total_msat, and the payment succeeds

Test that the sets are properly cleaned up after MPP_TIMEOUT
and the sender gets a second chance to pay the same invoice.
2025-11-27 17:57:25 +01:00
f321x
a91f7c519f tests: lnpeer: test_dont_settle_partial_mpp_trigger_with_invalid_cltv_htlc
Adds unittest to verify that lnpeer doesn't settle any htlcs of
incomplete mpp.
2025-11-27 17:57:23 +01:00
f321x
a7de8de5a2 tests: lnpeer: test_reject_multiple_payments_of_same_invoice
Test that lnpeer rejects incoming htlcs for payments that have already
been paid so invoices cannot be paid twice.
2025-11-27 17:57:21 +01:00
f321x
7840df2e0d tests: lnpeer: test_reject_payment_for_expired_invoice
Test that lnpeer is rejecting incoming htlcs for invoices that are
already expired.
2025-11-27 17:57:19 +01:00
f321x
da5f59903d tests: lnpeer: test_reject_invalid_min_final_cltv_delta
Add `test_reject_invalid_min_final_cltv_delta` which is supposed to test
that the peer rejects incoming htlcs with final cltv delta differing
from what has been requested in the lightning invoice.
2025-11-27 17:57:18 +01:00
f321x
0f314d1dd9 lnpeer/lnworker: refactor htlc_switch
refactor `htlc_switch` to new architecture to make it more robust
against partial settlement of htlc sets and increase maintainability.
Htlcs are now processed in two steps, first the htlcs are collected into
sets from the channels, and potentially failed on their own already.
Then a second loop iterates over the htlc sets and finalizes only on
whole sets.

# Conflicts:
#	electrum/lnpeer.py
2025-11-27 17:57:14 +01:00
f321x
41d391a617 Fix: For inner trampoline onions amt_to_forward can be larger than the htlc amount
Add unittest to TestPeerForwarding which sends a multi trampoline
payment.

Wait another htlc_switch iteration in tests because trampolines might have different delays
2025-11-27 17:44:31 +01:00
ghost43
8358a17ebb Merge pull request #10325 from f321x/debug_not_enough_balance
lightning: fix race when doing concurrent payments
2025-11-27 16:06:52 +00:00
f321x
196cc33c1c ln: fix race when doing concurrent ln payments
There is a race when initiating multiple lightning payments concurrently
(e.g. when doing a reverse swap with prepayment + swap payment).
suggest_splits might overallocate
split amounts for a channel as the splitting of both invoice amounts runs
concurrently and before acutal htlcs that reduce the channels balance
have been added to the channel yet. This results in a "not
enough balance" PaymentFailure once we try to send the htlcs and the
other payment attempt already reduced the available balance of the
channel.

This fix takes a lock from splitting the amount until the htlcs are
put on the channel, so suggest_splits always acts on the correct channel
balance.
2025-11-27 16:43:40 +01:00
Sander van Grieken
e137c888a1 qeconfig: fix btc amount regex, add msat regex property, add regex tests 2025-11-27 12:38:49 +01:00
Sander van Grieken
93c9dd9d12 qml: refactor invoice amount checks, msat precision for lightning.
add qeconfig unit tests for conversion methods.
2025-11-27 12:38:49 +01:00
f321x
a0455f8382 swaps: allow reverse swaps to external address
Implement logic to claim a reverse swap funding output to any given
address. This allows to do onchain payments to external recipients
through a submarine swap.
2025-11-27 09:50:04 +01:00
Sander van Grieken
23d5ed87e7 onion_message: move encrypt_onionmsg_tlv_hops_data() to lnonion as encrypt_hops_recipient_data()
and add support payloads other than onionmsg_tlv
2025-11-25 15:15:12 +01:00
ghost43
530260638a Merge pull request #10317 from f321x/fix_payto
cli: payto: fix feerate parsing
2025-11-21 18:37:08 +00:00
SomberNight
4fedab8bba fix tests: follow-up prev 2025-11-21 18:16:59 +00:00
f321x
114c48e452 cli: payto: fix feerate parsing
Feerate is passed to `Commands._get_fee_policy()` as str which then
tried to multiply the string by 1000. Now it first casts the string to
`Decimal` and multiplies the decimal.

Fixes https://github.com/spesmilo/electrum/issues/10315
2025-11-19 17:38:58 +01:00
ghost43
ee80065bb8 Merge pull request #10312 from SomberNight/202511_pr10230_1
lnonion: immutable OnionPacket and OnionHopsDataSingle
2025-11-18 16:41:19 +00:00
SomberNight
1b600b49e9 lnmsg/lnonion: follow-up prev: "hide" MappingProxyType usage 2025-11-18 14:54:33 +00:00
SomberNight
e52ed5073e test_wallet_vertical: add case spending mixed segwit/non-segwit UTXOs
I needed such a tx to test something in electrumx and wanted to copy-paste one from the electrum unit tests. Weird that we were lacking such a test case, I was fairly certain there was one already...
2025-11-17 19:20:36 +00:00
f321x
936e7fd1c2 lnonion: immutable OnionPacket and OnionHopsDataSingle
Make OnionHopsDataSingle and OnionPacket immutable for safer caching and
handling.

# Conflicts:
#	electrum/onion_message.py
2025-11-11 14:37:37 +01:00
Sander van Grieken
1ad6607405 onion_message: fix handling of ONION_MESSAGE_LARGE_SIZE payload sizes for onion messages,
process dummy hops regardless of EXPERIMENTAL_LN_FORWARD_PAYMENTS config option.
2025-11-10 16:20:15 +01:00
Sander van Grieken
9481f4f636 followup prev 2025-11-10 13:50:38 +01:00
Sander van Grieken
130af59760 update field naming for BOLT04 structures
see also: 3fffab3b88
2025-11-10 13:47:20 +01:00
ghost43
d87f9e9a44 Merge pull request #10295 from SomberNight/202510_proto16
electrum protocol: add support for 1.6, but keep supporting 1.4
2025-11-07 16:42:11 +00:00
ghost43
7cb5621625 Merge pull request #10274 from f321x/lnpay_collect_failed_htlcs
lnworker: collect failed htlcs during payment attempt, fix todo
2025-11-07 16:17:19 +00:00
SomberNight
e53666ac86 lnworker: follow-up prev: split pay_to_node 2025-11-07 15:37:49 +00:00
ThomasV
077bcf515d StoredDict: use pointers instead of path
Instead of storing its own path, each StoredDict element stores
its own key and a pointer to its parent. If a dict is removed
from the db, its parent pointer is set to None. This makes
self.path return None for all branches that have been pruned.

This passes tests/tests_json_db.py and fixes issue #10000
2025-11-07 10:00:10 +01:00
ThomasV
53c1817956 tests/test_jsondb.py: add tests that replace a StoredDict element
after its parent has been removed.

Related: #10000
2025-11-07 10:00:10 +01:00
SomberNight
e57087daf7 interface: implement support for protocol 1.6
ref https://github.com/spesmilo/electrum-protocol/pull/6
2025-11-03 18:32:48 +00:00
SomberNight
b1fc5b2461 tests: interface: fix estimatefee response (wrong unit) 2025-11-03 16:45:56 +00:00
SomberNight
325b83b30a tests: interface: add timeout to avoid hangs
instead of an infinite hang, the unit test should just fail
2025-11-03 16:44:47 +00:00
ghost43
0a414ad0f0 Merge pull request #10290 from SomberNight/202510_synchronizer_guess_status1
synchronizer: rm redundant get_history call if new block mined unconf
2025-11-03 15:45:26 +00:00