Commit Graph

17429 Commits

Author SHA1 Message Date
ShahanaFarooqui
ec7d247f38 docker: Added fixed SOURCE_DATE_EPOCH flag for reproducible Fedora build
- Using environment variable `SOURCE_DATE_EPOCH` with fixed value will enforce a consistent timestamp for Fedora build.
. Similar to Ubuntu fix in commit 490fb0fc3b
- Locked cargo version
- Add `no-cache` to Fedora build

Changelog-Fixed: Core lightning builds for Fedora on all systems are deterministic.
2026-01-16 12:34:03 -08:00
ShahanaFarooqui
12ccfb5c65 script: Add Fedora as target for SHASUMS verification 2026-01-16 12:34:03 -08:00
Alex Myers
9e490942af contrib: ignore cache when rebuilding docker builder images
This caused issues when dependencies were updated do to cached
images continuing to be used.

Changelog-None
2026-01-15 18:31:11 -08:00
ShahanaFarooqui
ae0e10875c doc: Update installation instruction on Fedora 2026-01-15 17:10:27 -08:00
ShahanaFarooqui
3f7565a3d2 docker: Update Fedora base image to 40
- Upgraded Fedora base image from 35 to 40. The existing Cargo failures were caused by the outdated Rust toolchain in Fedora 35. Cargo lockfile format v4 was introduced in Cargo 1.84 (December 2024), while Fedora 35 provides a Rust/Cargo version from roughly 2021–2022. As a result, the system Cargo could not parse modern Cargo.lock files, making it incompatible with current Rust projects.

- Added missing build dependencies to the Dockerfile, most notably the protobuf compiler (protoc).

Changelog-None: Upgraded Fedora version to 40 for reproducible build.
2026-01-15 17:10:27 -08:00
Rusty Russell
29465f5240 wallet: use correct derivation for elements when using mnemonic hsm_secret.
Even though we don't do taproot addresses on elements yet, use the
same scheme for simplicity and for future when we *do* do taproot.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2026-01-14 17:18:56 +10:30
Sangbida Chaudhuri
0269d0c0c9 jsonrpc: fix recover command for BIP86 wallets
The recover command checks if a node has already issued bitcoin
addresses before allowing recovery. This check only looked at
bip32_max_index, but with BIP86 wallets, newaddr() increments
bip86_max_index instead.

Also, the recover test asserted on hex but now it's asserting on codex32 instead. We should probably go in and fix the end point. @rustyrussell what do you think?
2026-01-14 17:18:56 +10:30
Sangbida Chaudhuri
e19fd5d62c wallet: change dev_listaddrs to also list bip86 addresses
listaddrs is dev only and used in tests so it's okay if we change the API here, the usage is by positional arguments in tests so we're okay. Also changing est_option_upfront_shutdown_script to handle both old hsmsecret and the newer mnemonic one.
2026-01-14 17:18:56 +10:30
Sangbida Chaudhuri
5fdc56c544 wallet/hsmd: fix signmessagewithkey for BIP86 wallets
The signmessagewithkey RPC was failing for BIP86 (mnemonic-based)
wallets because:

1. The wallet RPC was iterating through BIP32-derived addresses only,
   so it couldn't find BIP86-derived addresses.

2. The HSM's handle_bip137_sign_message always used bitcoin_key()
   (BIP32 derivation) regardless of wallet type.
2026-01-14 17:18:56 +10:30
Sangbida Chaudhuri
c17590379e lightningd: use BIP86 derivation in p2wpkh_for_keyidx when available
When a peer doesn't support OPT_SHUTDOWN_ANYSEGWIT, we fall back to P2WPKH for the shutdown script. For BIP86 wallets, we need to use bip86_pubkey for derivation (matching p2tr_for_keyidx), otherwise the resulting script won't be recognized after restart.
2026-01-14 17:18:56 +10:30
Sangbida Chaudhuri
4106a212ec lightningd: add p2wpkh script for bip86 base
A bech32 address can be generated from a bip86 base so we should add both script types (p2wpkh, p2tr) to the txfilter for bip86 bases.
2026-01-14 17:18:56 +10:30
Sangbida Chaudhuri
4b1f2a079e lightningd: use BIP86 derivation for P2TR in HTLC rebroadcast change outputs 2026-01-14 17:18:56 +10:30
Sangbida Chaudhuri
fa96b60113 lightningd: use bip86 derivation for anchor spend change outputs 2026-01-14 17:18:56 +10:30
Sangbida Chaudhuri
bf43fbb7cc lightningd: Fix penalty tx output derivation for BIP86 wallets
When using the new BIP39 mnemonic HSM secret format, the wallet uses
BIP86 derivation for taproot addresses. However, onchaind_tx_unsigned() was always using bip32_pubkey() to derive the final key for penalty transaction outputs.
2026-01-14 17:18:56 +10:30
Rusty Russell
9b85ce7b03 hsmd: fix derivation for non-taproot addresses in modern mnemonic (25.12+) nodes.
This is a fix from https://github.com/rauaap who correctly diagnosed the problem:

```
Error broadcasting transaction: error code: -26\nerror message\nmempool-script-verify-flag-failed (Script failed an OP_EQUALVERIFY operation), input 0 of ...
```

The decision to use the changed derivation for all addresses, not just
taproot, came up during review.  Unfortunately, the signing code
(here) was not changed to match the address generation code (in the
wallet).

Reported-by: https://github.com/postanissue
Fixes: https://github.com/ElementsProject/lightning/issues/8804
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
Changelog-Fixed: lightningd: we now correctly sign for non-taproot addresses given by nodes created by v25.12 or newer.
2026-01-14 17:18:56 +10:30
Rusty Russell
d2123a94a5 lightning-hsmtool: fix dumponchaindescriptors for mnemonic hsm_secrets.
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
Changelog-Fixed: `lightning-hsmtool`: handle mnemonic hsm_secret files (nodes created >= v25.12).
2026-01-14 17:18:56 +10:30
Rusty Russell
9c6430c076 plugins/pay: don't crash if erring index is past route array end.
I assume this happens with multi-hop routehints?

```
1768169599027	2026-01-11T22:13:19.027Z	pay: plugins/libplugin-pay.c:1199: payment_result_infer: Assertion `i <= len' failed.
1768169599027	2026-01-11T22:13:19.027Z	pay: FATAL SIGNAL 6 (version 25.12)
1768169599036	2026-01-11T22:13:19.036Z	0x5562816bcaa4 send_backtrace
1768169599036	2026-01-11T22:13:19.036Z		common/daemon.c:38
1768169599036	2026-01-11T22:13:19.036Z	0x5562816bcb40 crashdump
1768169599036	2026-01-11T22:13:19.036Z		common/daemon.c:83
1768169599036	2026-01-11T22:13:19.036Z	0x7f5fca29d32f ???
1768169599036	2026-01-11T22:13:19.036Z		???:0
1768169599036	2026-01-11T22:13:19.036Z	0x7f5fca2f6b2c ???
1768169599036	2026-01-11T22:13:19.036Z		pthread_kill+0x11c:0
1768169599036	2026-01-11T22:13:19.036Z	0x7f5fca29d27d ???
1768169599036	2026-01-11T22:13:19.036Z		gsignal+0x1d:0
1768169599036	2026-01-11T22:13:19.036Z	0x7f5fca2808fe ???
1768169599036	2026-01-11T22:13:19.036Z		abort+0xde:0
1768169599036	2026-01-11T22:13:19.036Z	0x7f5fca28081a ???
1768169599036	2026-01-11T22:13:19.036Z		???:0
1768169599036	2026-01-11T22:13:19.036Z	0x7f5fca293516 ???
1768169599036	2026-01-11T22:13:19.036Z		__assert_fail+0x46:0
1768169599037	2026-01-11T22:13:19.037Z	0x5562816ae9f6 payment_result_infer
1768169599037	2026-01-11T22:13:19.037Z		plugins/libplugin-pay.c:1199
1768169599037	2026-01-11T22:13:19.037Z	0x5562816b4acd payment_waitsendpay_finished
1768169599037	2026-01-11T22:13:19.037Z		plugins/libplugin-pay.c:1653
1768169599037	2026-01-11T22:13:19.037Z	0x5562816aca60 handle_rpc_reply
1768169599037	2026-01-11T22:13:19.037Z		plugins/libplugin.c:1062
1768169599037	2026-01-11T22:13:19.037Z	0x5562816acc86 rpc_conn_read_response
1768169599037	2026-01-11T22:13:19.037Z		plugins/libplugin.c:1377
1768169599037	2026-01-11T22:13:19.037Z	0x5562816f0e87 next_plan
1768169599037	2026-01-11T22:13:19.037Z		ccan/ccan/io/io.c:60
1768169599037	2026-01-11T22:13:19.037Z	0x5562816f1358 do_plan
1768169599037	2026-01-11T22:13:19.037Z		ccan/ccan/io/io.c:422
1768169599037	2026-01-11T22:13:19.037Z	0x5562816f1415 io_ready
1768169599037	2026-01-11T22:13:19.037Z		ccan/ccan/io/io.c:439
1768169599037	2026-01-11T22:13:19.037Z	0x5562816f2e23 io_loop
1768169599037	2026-01-11T22:13:19.037Z		ccan/ccan/io/poll.c:470
1768169599037	2026-01-11T22:13:19.037Z	0x5562816ae114 plugin_main
1768169599037	2026-01-11T22:13:19.037Z		plugins/libplugin.c:2429
1768169599037	2026-01-11T22:13:19.037Z	0x5562816a894c main
1768169599037	2026-01-11T22:13:19.037Z		plugins/pay.c:1581
1768169599037	2026-01-11T22:13:19.037Z	0x7f5fca2821c9 ???
1768169599037	2026-01-11T22:13:19.037Z		???:0
1768169599037	2026-01-11T22:13:19.037Z	0x7f5fca28228a ???
1768169599037	2026-01-11T22:13:19.037Z		__libc_start_main+0x8a:0
1768169599037	2026-01-11T22:13:19.037Z	0x5562816a4eb4 ???
1768169599037	2026-01-11T22:13:19.037Z		_start+0x24:0
1768169599037	2026-01-11T22:13:19.037Z	0xffffffffffffffff ???
1768169599037	2026-01-11T22:13:19.037Z		???:0
1768169599136	2026-01-11T22:13:19.136Z	2026-01-11T22:13:19.136Z INFO    plugin-pay: Killing plugin: exited during normal operation
69599136	2026-01-11T22:13:19.136Z	2026-01-11T22:13:19.136Z **BROKEN** plugin-pay: Plugin marked as important, shutting down lightningd!
```

Reported-by: michael1011
Fixes: https://github.com/ElementsProject/lightning/issues/8828
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
Changelog-Fixed: plugins: `pay` can crash on errors returned from deep inside routehints.
2026-01-14 17:06:02 +10:30
Rusty Russell
35e703bfe1 askrene: don't crash if refining flow which has capacity greaater than max it should have.
```
1767724611265   2026-01-06T18:36:51.265Z                plugins/libplugin.c:1073
1767724611265   2026-01-06T18:36:51.265Z        0x55fc0c1428ac handle_rpc_reply
1767724611264   2026-01-06T18:36:51.264Z                plugins/askrene/askrene.c:801
1767724611264   2026-01-06T18:36:51.264Z        0x55fc0c13174c listpeerchannels_done
1767724611264   2026-01-06T18:36:51.264Z                plugins/askrene/askrene.c:669
1767724611264   2026-01-06T18:36:51.264Z        0x55fc0c130f55 do_getroutes
1767724611264   2026-01-06T18:36:51.264Z                plugins/askrene/mcf.c:1636
1767724611264   2026-01-06T18:36:51.264Z        0x55fc0c138bd7 default_routes
1767724611264   2026-01-06T18:36:51.264Z                plugins/askrene/mcf.c:1415
1767724611264   2026-01-06T18:36:51.264Z        0x55fc0c1382ec linear_routes
1767724611264   2026-01-06T18:36:51.264Z                plugins/askrene/refine.c:510
1767724611264   2026-01-06T18:36:51.264Z        0x55fc0c13b110 refine_flows
1767724611264   2026-01-06T18:36:51.264Z                plugins/askrene/refine.c:449
1767724611264   2026-01-06T18:36:51.264Z        0x55fc0c13ac9f increase_flows
1767724611264   2026-01-06T18:36:51.264Z                abort+0xde:0
```

Fixes: #8823
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
Changelog-Fixed: plugins: `askrene` can crash on a corner case in increase_flows.
2026-01-14 17:06:02 +10:30
Rusty Russell
b0f8077e32 pytest: fix flake in test_gossip_query_channel_range
If l4 sends a WIRE_QUERY_SHORT_CHANNEL_IDS at the wrong time, we will
get that and be upset the response is wrong:

```
2026-01-13T14:45:55.9059786Z E       AssertionError: assert ['010806226e46111a0b59caaf126043eb5bbf28c34f3a5e332a1fc7b2b73cf188910f00000000000f42400100110000006800000100000000690000010000', '010506226e46111a0b59caaf126043eb5bbf28c34f3a5e332a1fc7b2b73cf188910f001100000068000001000000006900000100000103000402'] in (['010806226e46111a0b59caaf126043eb5bbf28c34f3a5e332a1fc7b2b73cf188910f00000000000f42400100110000006800000100000000690000010000'], ['010806226e46111a0b59caaf126043eb5bbf28c34f3a5e332a1fc7b2b73cf188910f00000000000f42400100110000006900000100000000680000010000'])
2026-01-13T14:45:55.9063357Z 
2026-01-13T14:45:55.9063527Z tests/test_gossip.py:762: AssertionError
```

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2026-01-14 15:41:45 +10:30
Rusty Russell
84afe57919 pytest: disable autoreconnect on test_sql to avoid reconnect race.
Because l1 and l3 allow localhost as a broadcastable address, they can
try to reconnect.  Disable reconnections, so we don't race:

```
>       l2.rpc.connect(l3.info['id'], 'localhost', l3.port)

tests/test_plugin.py:4146: 
...	    
        elif "error" in resp:
>           raise RpcError(method, payload, resp['error'])
E           pyln.client.lightning.RpcError: RPC call failed: method: connect, payload: {'id': '035d2b1192dfba134e10e540875d366ebc8bc353d5aa766b80c090b39c3a5d885d', 'host': 'localhost', 'port': 45035}, error: {'code': 402, 'message': 'disconnected during connection'}
```

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2026-01-14 15:41:45 +10:30
Rusty Russell
3be25d48d3 pytest: don't rely on sleep to ensure wait commands have been submitted.
Seems like sleep(1) isn't always enough.  Give in and put a log
message there, and use that:

```
	waitfut = executor.submit(l2.rpc.wait, subsystem='forwards', indexname='deleted', nextvalue=1)
        time.sleep(1)
    
        l2.rpc.delforward(scid12, 1, 'failed')
    
        waitres = waitfut.result(TIMEOUT)
>       assert waitres == {'subsystem': 'forwards',
                           'deleted': 1,
                           'forwards': {'in_channel': scid12,
                                        'in_htlc_id': 1,
                                        'status': 'failed'}}
E       AssertionError: assert {'subsystem': 'forwards', 'deleted': 1} == {'subsystem': 'forwards', 'deleted': 1, 'forwards': {'in_channel': '103x2x0', 'in_htlc_id': 1, 'status': 'failed'}}
E         
E         Common items:
E         {'deleted': 1, 'subsystem': 'forwards'}
E         Right contains 1 more item:
E         {'forwards': {'in_channel': '103x2x0', 'in_htlc_id': 1, 'status': 'failed'}}
E         
E         Full diff:
E           {
E               'deleted': 1,
E         -     'forwards': {
E         -         'in_channel': '103x2x0',
E         -         'in_htlc_id': 1,
E         -         'status': 'failed',
E         -     },
E               'subsystem': 'forwards',
E           }

tests/test_misc.py:3599: AssertionError
```

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2026-01-14 15:41:45 +10:30
Rusty Russell
fd64bb114b lightningd: fix bogus memleak report.
We do our own leak detection on a reply from a subd, but the reply
code set subd->conn to NULL (saving it temporarily, in case the subd
is freed), resulting in it being seen as a leak:

```
lightningd-2 2026-01-12T14:11:12.677Z DEBUG   0266e4598d1d3c415f572a8488830b60f7e744ed9235eb0b1ba93283b315c03518-channeld-chan#1: billboard perm: Reconnected, and reestablished.
lightningd-2 2026-01-12T14:11:12.677Z DEBUG   0266e4598d1d3c415f572a8488830b60f7e744ed9235eb0b1ba93283b315c03518-channeld-chan#1: billboard: Channel ready for use. Shutdown messages exchanged.
lightningd-1 2026-01-12T14:11:12.705Z DEBUG   022d223620a359a47ff7f7ac447c85c46c923da53389221a0054c11c1e3ca31d59-closingd-chan#1: pid 100718, msgfd 87
lightningd-1 2026-01-12T14:11:12.705Z DEBUG   022d223620a359a47ff7f7ac447c85c46c923da53389221a0054c11c1e3ca31d59-channeld-chan#1: Status closed, but not exited. Killing
...
lightningd-1 2026-01-12T14:11:32.546Z **BROKEN** lightningd: MEMLEAK: 0x55f61eb4d848
lightningd-1 2026-01-12T14:11:32.546Z **BROKEN** lightningd:   label=ccan/ccan/io/io.c:92:struct io_conn
lightningd-1 2026-01-12T14:11:32.546Z **BROKEN** lightningd:   alloc:
lightningd-1 2026-01-12T14:11:32.840Z **BROKEN** lightningd:     ccan/ccan/tal/tal.c:488 (tal_alloc_)
lightningd-1 2026-01-12T14:11:32.845Z **BROKEN** lightningd:     ccan/ccan/io/io.c:92 (io_new_conn_)
lightningd-1 2026-01-12T14:11:32.845Z **BROKEN** lightningd:     lightningd/subd.c:785 (new_subd)
lightningd-1 2026-01-12T14:11:32.845Z **BROKEN** lightningd:     lightningd/subd.c:839 (new_channel_subd_)
lightningd-1 2026-01-12T14:11:32.846Z **BROKEN** lightningd:     lightningd/channel_control.c:1714 (peer_start_channeld)
lightningd-1 2026-01-12T14:11:32.847Z **BROKEN** lightningd:     lightningd/peer_control.c:1390 (connect_activate_subd)
lightningd-1 2026-01-12T14:11:32.847Z **BROKEN** lightningd:     lightningd/peer_control.c:1516 (peer_connected_hook_final)
lightningd-1 2026-01-12T14:11:32.847Z **BROKEN** lightningd:     lightningd/plugin_hook.c:243 (hook_done)
lightningd-1 2026-01-12T14:11:32.847Z **BROKEN** lightningd:     lightningd/plugin_hook.c:343 (plugin_hook_call_next)
lightningd-1 2026-01-12T14:11:32.847Z **BROKEN** lightningd:     lightningd/plugin_hook.c:299 (plugin_hook_callback)
lightningd-1 2026-01-12T14:11:32.851Z **BROKEN** lightningd:     lightningd/plugin.c:701 (plugin_response_handle)
lightningd-1 2026-01-12T14:11:32.851Z **BROKEN** lightningd:     lightningd/plugin.c:790 (plugin_read_json)
lightningd-1 2026-01-12T14:11:32.851Z **BROKEN** lightningd:     ccan/ccan/io/io.c:60 (next_plan)
lightningd-1 2026-01-12T14:11:32.851Z **BROKEN** lightningd:     ccan/ccan/io/io.c:422 (do_plan)
lightningd-1 2026-01-12T14:11:32.851Z **BROKEN** lightningd:     ccan/ccan/io/io.c:439 (io_ready)
lightningd-1 2026-01-12T14:11:32.851Z **BROKEN** lightningd:     ccan/ccan/io/poll.c:470 (io_loop)
lightningd-1 2026-01-12T14:11:32.851Z **BROKEN** lightningd:     lightningd/io_loop_with_timers.c:22 (io_loop_with_timers)
lightningd-1 2026-01-12T14:11:32.851Z **BROKEN** lightningd:     lightningd/lightningd.c:1492 (main)
lightningd-1 2026-01-12T14:11:32.852Z **BROKEN** lightningd:     ../sysdeps/nptl/libc_start_call_main.h:58 (__libc_start_call_main)
lightningd-1 2026-01-12T14:11:32.852Z **BROKEN** lightningd:     ../csu/libc-start.c:360 (__libc_start_main_impl)
lightningd-1 2026-01-12T14:11:32.852Z **BROKEN** lightningd:   parents:
lightningd-1 2026-01-12T14:11:32.852Z **BROKEN** lightningd:     lightningd/lightningd.c:108:struct lightningd
lightningd-1 2026-01-12T14:11:32.853Z DEBUG   lightningd: channel_gossip: no longer in startup mode
lightningd-1 2026-01-12T14:11:32.856Z DEBUG   hsmd: new_client: 1
```

The workaround is to do our own leak detection on a timer (making the
conn notleak() would leave us open to a real leak in future!).

We also move the `struct leak_detect` definition inside the C file
where it belongs.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2026-01-14 15:41:45 +10:30
Rusty Russell
c10c54ff23 pytest: don't record IO when we kill nodes
```
ERROR tests/test_connection.py::test_channel_persistence - json.decoder.JSONDecodeError: Expecting value: line 1 column 1 (char 0)
```

Similarly:

```
ERROR tests/test_opening.py::test_sendpsbt_crash - json.decoder.JSONDecodeError: Expecting value: line 1 column 1 (char 0)
```

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2026-01-14 15:41:45 +10:30
Rusty Russell
8d807be6bf pytest: fix reconnect flake in test_route_by_old_scid
We restart l2, then try to connect to l1.  But l1 will be trying to
reconnect (and it can, since it was initially given l2's address), so
it can race us and we end up disconnecting because of simultaneous
connect:

```
2026-01-13T04:06:10.7490260Z >       l2.rpc.connect(l1.info['id'], 'localhost', l1.port)
2026-01-13T04:06:10.7490667Z 
2026-01-13T04:06:10.7490828Z tests/test_splicing.py:554: 
...
2026-01-13T04:06:10.7525780Z >           raise RpcError(method, payload, resp['error'])
2026-01-13T04:06:10.7527464Z E           pyln.client.lightning.RpcError: RPC call failed: method: connect, payload: {'id': '0266e4598d1d3c415f572a8488830b60f7e744ed9235eb0b1ba93283b315c03518', 'host': 'localhost', 'port': 46813}, error: {'code': 402, 'message': 'disconnected during connection'}
2026-01-13T04:06:10.7528832Z
...
2026-01-13T04:06:10.9411680Z lightningd-2 2026-01-13T03:59:59.463Z DEBUG   0266e4598d1d3c415f572a8488830b60f7e744ed9235eb0b1ba93283b315c03518-connectd: Connect OUT
2026-01-13T04:06:10.9412178Z lightningd-2 2026-01-13T03:59:59.463Z DEBUG   0266e4598d1d3c415f572a8488830b60f7e744ed9235eb0b1ba93283b315c03518-connectd: peer_out WIRE_INIT
2026-01-13T04:06:10.9412551Z lightningd-2 2026-01-13T03:59:59.463Z DEBUG   0266e4598d1d3c415f572a8488830b60f7e744ed9235eb0b1ba93283b315c03518-connectd: Connect IN
2026-01-13T04:06:10.9412947Z lightningd-2 2026-01-13T03:59:59.464Z DEBUG   0266e4598d1d3c415f572a8488830b60f7e744ed9235eb0b1ba93283b315c03518-connectd: peer_out WIRE_INIT
2026-01-13T04:06:10.9413342Z lightningd-2 2026-01-13T03:59:59.464Z DEBUG   0266e4598d1d3c415f572a8488830b60f7e744ed9235eb0b1ba93283b315c03518-connectd: peer_in WIRE_INIT
2026-01-13T04:06:10.9413624Z lightningd-2 2026-01-13T03:59:59.487Z TRACE   lightningd: Calling peer_connected hook of plugin chanbackup
2026-01-13T04:06:10.9414057Z lightningd-2 2026-01-13T03:59:59.534Z DEBUG   0266e4598d1d3c415f572a8488830b60f7e744ed9235eb0b1ba93283b315c03518-connectd: Handed peer, entering loop
2026-01-13T04:06:10.9414451Z lightningd-2 2026-01-13T03:59:59.534Z DEBUG   0266e4598d1d3c415f572a8488830b60f7e744ed9235eb0b1ba93283b315c03518-connectd: peer_in WIRE_INIT
2026-01-13T04:06:10.9414851Z lightningd-2 2026-01-13T03:59:59.574Z DEBUG   0266e4598d1d3c415f572a8488830b60f7e744ed9235eb0b1ba93283b315c03518-lightningd: peer reconnected
2026-01-13T04:06:10.9415250Z lightningd-2 2026-01-13T03:59:59.609Z DEBUG   0266e4598d1d3c415f572a8488830b60f7e744ed9235eb0b1ba93283b315c03518-lightningd: peer_disconnected
2026-01-13T04:06:10.9415527Z lightningd-2 2026-01-13T03:59:59.685Z TRACE   lightningd: Calling peer_connected hook of plugin chanbackup
2026-01-13T04:06:10.9415957Z lightningd-2 2026-01-13T03:59:59.687Z DEBUG   0266e4598d1d3c415f572a8488830b60f7e744ed9235eb0b1ba93283b315c03518-connectd: Handed peer, entering loop
2026-01-13T04:06:10.9416364Z lightningd-2 2026-01-13T03:59:59.757Z DEBUG   0266e4598d1d3c415f572a8488830b60f7e744ed9235eb0b1ba93283b315c03518-lightningd: peer_disconnected
2026-01-13T04:06:10.9417067Z lightningd-2 2026-01-13T03:59:59.830Z DEBUG   0266e4598d1d3c415f572a8488830b60f7e744ed9235eb0b1ba93283b315c03518-connectd: Will try reconnect in 4 seconds
```

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2026-01-14 15:41:45 +10:30
Rusty Russell
c0c885492f pytest: another flake in test_important_plugin.
There's one more complaint we can see when plugins get upset:

```
lightningd-1 2026-01-12T06:10:49.317Z **BROKEN** plugin-cln-xpay: askrene-create-layer failed with {"code":-4, "message":"Plugin terminated before replying to RPC call."}
```

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2026-01-14 15:41:45 +10:30
Sangbida Chaudhuri
b219214a55 doc: Update docs to reflect new hsm secret format
Changelog-Changed - Updated backup and hsm secret docs to reflect mnemonic based hsm secret
2026-01-14 15:33:14 +10:30
Rusty Russell
779a478437 lightningd: allow --recover / recover JSON RPC to take mnemonic.
In fact, you *must* use mnemonic to successfully recover a modern node!

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
Changelog-Changed: JSON-RPC: `recover` takes a 12-word mnemonic for nodes created by v25.12 or later.
2026-01-13 22:36:01 +10:30
Rusty Russell
4f5e5aad18 common: expose validate_mnemonic so the option can use it.
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2026-01-13 22:36:01 +10:30
Rusty Russell
f975bb37d4 lightning-hsmtool: support extracting the mnemonic from hsm_secret.
We cannot use the codex32 or raw hex for recovery of 25.12 nodes,
since they will then use the incorrect derivation for all paths, and
be unable to spend (or even find!) their funds.

So implement `getsecret` to replace `getcodexsecret`.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
Changelog-Changed: `lightning-hsmtool`: `getsecret` replaces `getcodexsecret` for modern nodes (gives mnemonic).
Changelog-Deprecated: `lightning-hsmtool`: `getcodexsecret`.  Use `getsecret`.
2026-01-13 22:36:01 +10:30
Lagrang3
118e474637 askrene: fix payment crash
Changelog-Fixed: askrene: fix a plugin crash triggered during single path payments when a channel fees doesn't fit u32.

Signed-off-by: Lagrang3 <lagrang3@protonmail.com>
2026-01-13 15:16:46 +10:30
Lagrang3
a0cc50cf8e askrene: regression test that triggers assertion
cln-askrene: plugins/askrene/mcf.c:474: combine_cost_function: Assertion `fcost != INFINITE' failed.
cln-askrene: FATAL SIGNAL 6 (version v25.12-131-gb15f386-modded)
0x55703f242fd1 send_backtrace
	common/daemon.c:38
0x55703f24305b crashdump
	common/daemon.c:83
0x7f548b421def ???
	./signal/../sysdeps/unix/sysv/linux/x86_64/libc_sigaction.c:0
0x7f548b47695c __pthread_kill_implementation
	./nptl/pthread_kill.c:44
0x7f548b421cc1 __GI_raise
	../sysdeps/posix/raise.c:26
0x7f548b40a4ab __GI_abort
	./stdlib/abort.c:73
0x7f548b40a41f __assert_fail_base
	./assert/assert.c:118
0x55703f234491 combine_cost_function
	plugins/askrene/mcf.c:474
0x55703f2358b6 single_path_flow
	plugins/askrene/mcf.c:1213
0x55703f235fa2 linear_routes
	plugins/askrene/mcf.c:1411
0x55703f236804 single_path_routes
	plugins/askrene/mcf.c:1656
0x55703f22edad do_getroutes
	plugins/askrene/askrene.c:689
0x55703f22f269 json_getroutes
	plugins/askrene/askrene.c:910
0x55703f2411a7 ld_command_handle
	plugins/libplugin.c:2155
0x55703f2413b1 ld_read_json
	plugins/libplugin.c:2231
0x55703f271a4d next_plan
	ccan/ccan/io/io.c:60
0x55703f271ed8 do_plan
	ccan/ccan/io/io.c:422
0x55703f271f91 io_ready
	ccan/ccan/io/io.c:439
0x55703f27391b io_loop
	ccan/ccan/io/poll.c:470
0x55703f2417fd plugin_main
	plugins/libplugin.c:2429
0x55703f22f753 main
	plugins/askrene/askrene.c:1452
0x7f548b40bca7 __libc_start_call_main
	../sysdeps/nptl/libc_start_call_main.h:58
0x7f548b40bd64 __libc_start_main_impl
	../csu/libc-start.c:360
0x55703f22baa0 ???
	_start+0x20:0
0xffffffffffffffff ???
	???:0

Changelog-None

Signed-off-by: Lagrang3 <lagrang3@protonmail.com>
2026-01-13 15:16:46 +10:30
ShahanaFarooqui
b895700fe2 tools: Update libsodium version for Ubuntu Noble
Changelog-None: Fixes release process only.
2026-01-12 18:00:09 -06:00
Rusty Russell
b15f386df6 pytest: fix bad gossip flake in test_buy_liquidity_ad_check_bookkeeping
If we don't wait for the channel announcement to be processed, we can
get bad gossip:

```
lightningd-2 2026-01-08T04:53:53.795Z DEBUG   0266e4598d1d3c415f572a8488830b60f7e744ed9235eb0b1ba93283b315c03518-chan#2: Funding tx 2f41b1cc99dea016b7feddbeb1f31ae21b30f56d77ecb2ecb2b2f0faff4808fe depth 12 of 1
lightningd-2 2026-01-08T04:53:53.795Z DEBUG   0266e4598d1d3c415f572a8488830b60f7e744ed9235eb0b1ba93283b315c03518-chan#2: Funding tx 2f41b1cc99dea016b7feddbeb1f31ae21b30f56d77ecb2ecb2b2f0faff4808fe confirmed, but peer in state ONCHAIN
lightningd-2 2026-01-08T04:53:53.802Z DEBUG   0266e4598d1d3c415f572a8488830b60f7e744ed9235eb0b1ba93283b315c03518-onchaind-chan#2: Got new message WIRE_ONCHAIND_DEPTH
lightningd-2 2026-01-08T04:53:53.802Z DEBUG   0266e4598d1d3c415f572a8488830b60f7e744ed9235eb0b1ba93283b315c03518-onchaind-chan#2: Sending 0 missing htlc messages
lightningd-2 2026-01-08T04:53:53.802Z DEBUG   0266e4598d1d3c415f572a8488830b60f7e744ed9235eb0b1ba93283b315c03518-onchaind-chan#2: FUNDING_TRANSACTION/FUNDING_OUTPUT->MUTUAL_CLOSE depth 6
lightningd-2 2026-01-08T04:53:53.802Z DEBUG   0266e4598d1d3c415f572a8488830b60f7e744ed9235eb0b1ba93283b315c03518-onchaind-chan#2: billboard: All outputs resolved: waiting 94 more blocks before forgetting channel
lightningd-2 2026-01-08T04:53:53.812Z DEBUG   gossipd: gossmap_manage: new block, adding 104x1x1 to pending...
lightningd-2 2026-01-08T04:53:53.812Z DEBUG   gossipd: REPLY WIRE_GOSSIPD_NEW_BLOCKHEIGHT_REPLY with 0 fds
lightningd-1 2026-01-08T04:53:53.819Z DEBUG   022d223620a359a47ff7f7ac447c85c46c923da53389221a0054c11c1e3ca31d59-connectd: peer_in WIRE_WARNING
lightningd-1 2026-01-08T04:53:53.820Z DEBUG   022d223620a359a47ff7f7ac447c85c46c923da53389221a0054c11c1e3ca31d59-connectd: Received WIRE_WARNING: WARNING: channel_announcement: no unspent txout 104x1x1
lightningd-2 2026-01-08T04:53:53.820Z TRACE   gossipd: channel_announcement: got reply for 104x1x1...
lightningd-2 2026-01-08T04:53:53.820Z TRACE   0266e4598d1d3c415f572a8488830b60f7e744ed9235eb0b1ba93283b315c03518-gossipd: Bad gossip order: channel_announcement: no unspent txout 104x1x1
lightningd-2 2026-01-08T04:53:53.820Z DEBUG   0266e4598d1d3c415f572a8488830b60f7e744ed9235eb0b1ba93283b315c03518-connectd: peer_out WIRE_WARNING
```

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2026-01-08 22:33:19 +10:30
Rusty Russell
3d59af6f98 pytest: fix coinmoves flake, where routing credit/debit can appear in either order.
It's done as HTLCs finalize, but we can close the incoming HTLC as soon as we get the
preimage, so that entire thing could finish before the outgoing HTLC.

```
>       check_channel_moves(l1, expected_channel1)

tests/test_coinmoves.py:307: 
...
E         Full diff:
E           [
E               {
E                   'account_id': '58d371ab100e0ea847a11c9550add273ef8531bc12bb51b0e30c8f833506a772',
E                   'created_index': 1,
E                   'credit_msat': 0,
E                   'debit_msat': 1000000,
E                   'fees_msat': 0,
E                   'group_id': 1318196858430961660,
E                   'part_id': 1,
E                   'payment_hash': '8da829ab29715106a4e767facc0b58776ae5bfc11c4e9dcda3063013e1ef8ef0',
E                   'primary_tag': 'invoice',
E               },
E               {
E                   'account_id': '0b872506f67b363803cd85cf9ff6807ebc1dc8a4521aa191386b4c5366d490d7',
E                   'created_index': 2,
E                   'credit_msat': 100000,
E                   'debit_msat': 0,
E                   'fees_msat': 0,
E                   'primary_tag': 'pushed',
E               },
E               {
E         +         'account_id': '0b872506f67b363803cd85cf9ff6807ebc1dc8a4521aa191386b4c5366d490d7',
E         +         'created_index': 3,
E         +         'credit_msat': 10000100001,
E         +         'debit_msat': 0,
E         +         'fees_msat': 100001,
E         +         'payment_hash': '0ebfa5387de5fd12c15089833b0193fb6007e9f494ec24d479e327a96ac8e8c0',
E         +         'primary_tag': 'routed',
E         +     },
E         +     {
E                   'account_id': '58d371ab100e0ea847a11c9550add273ef8531bc12bb51b0e30c8f833506a772',
E         -         'created_index': 3,
E         ?                          ^
E         +         'created_index': 4,
E         ?                          ^
E                   'credit_msat': 0,
E                   'debit_msat': 10000000000,
E                   'fees_msat': 100001,
E                   'payment_hash': '0ebfa5387de5fd12c15089833b0193fb6007e9f494ec24d479e327a96ac8e8c0',
E                   'primary_tag': 'routed',
E               },
E         -     {
E         -         'account_id': '0b872506f67b363803cd85cf9ff6807ebc1dc8a4521aa191386b4c5366d490d7',
E         -         'created_index': 4,
E         -         'credit_msat': 10000100001,
E         -         'debit_msat': 0,
E         -         'fees_msat': 100001,
E         -         'payment_hash': '0ebfa5387de5fd12c15089833b0193fb6007e9f494ec24d479e327a96ac8e8c0',
E         -         'primary_tag': 'routed',
E         -     },
E           ]
```
2026-01-08 22:33:19 +10:30
Rusty Russell
25bad01bbe pytest: fix flake in test_coinmoves_unilateral_htlc_timeout
We need to make sure anchor reaches bitcoind, otherwise it might mine
the commitment tx without it.  This can happen in
test_coinmoves_unilateral_htlc_fulfill as well.

```
>       check_chain_moves(l1, expected_chain1)

tests/test_coinmoves.py:844: 
...
E         Full diff:
E           [
E               {
E                   'account_id': 'wallet',
E                   'blockheight': 102,
E                   'created_index': 1,
E                   'credit_msat': 100000000000,
E                   'debit_msat': 0,
E                   'extra_tags': [],
E                   'output_msat': 100000000000,
E                   'primary_tag': 'deposit',
E                   'utxo': 'fca99b85e58f8ae23e5c6872e0500784997deb98bfc92e43449206553a108db2:1',
E               },
E               {
E                   'account_id': 'wallet',
E                   'blockheight': 103,
E                   'created_index': 2,
E                   'credit_msat': 0,
E                   'debit_msat': 100000000000,
E                   'extra_tags': [],
E                   'output_msat': 100000000000,
E                   'primary_tag': 'withdrawal',
E                   'spending_txid': 'c097ad8bde478396c961369b69c50a144fae3423f36af4554f3fb1dacfdff83f',
E                   'utxo': 'fca99b85e58f8ae23e5c6872e0500784997deb98bfc92e43449206553a108db2:1',
E               },
E               {
E                   'account_id': 'wallet',
E                   'blockheight': 103,
E                   'created_index': 3,
E                   'credit_msat': 25000000,
E                   'debit_msat': 0,
E                   'extra_tags': [],
E                   'output_msat': 25000000,
E                   'primary_tag': 'deposit',
E                   'utxo': 'c097ad8bde478396c961369b69c50a144fae3423f36af4554f3fb1dacfdff83f:1',
E               },
E               {
E                   'account_id': '3ff8dfcfdab13f4f55f46af32334ae4f140ac5699b3661c9968347de8bad97c0',
E                   'blockheight': 103,
E                   'created_index': 4,
E                   'credit_msat': 99970073000,
E                   'debit_msat': 0,
E                   'extra_tags': [
E                       'opener',
E                   ],
E                   'output_msat': 99970073000,
E                   'peer_id': '022d223620a359a47ff7f7ac447c85c46c923da53389221a0054c11c1e3ca31d59',
E                   'primary_tag': 'channel_open',
E                   'utxo': 'c097ad8bde478396c961369b69c50a144fae3423f36af4554f3fb1dacfdff83f:0',
E               },
E               {
E         -         'account_id': 'wallet',
E         +         'account_id': '3ff8dfcfdab13f4f55f46af32334ae4f140ac5699b3661c9968347de8bad97c0',
E                   'blockheight': 104,
E                   'created_index': 5,
E         -         'credit_msat': 0,
E         -         'debit_msat': 25000000,
E         -         'extra_tags': [],
E         -         'output_msat': 25000000,
E         -         'primary_tag': 'withdrawal',
E         -         'spending_txid': '1b6fbf9887d6f9cce727fc8bf9f582a3353be682998d4bafc9691c9ed26897e7',
E         -         'utxo': 'c097ad8bde478396c961369b69c50a144fae3423f36af4554f3fb1dacfdff83f:1',
E         -     },
E         -     {
E         -         'account_id': 'wallet',
E         -         'blockheight': 104,
E         -         'created_index': 6,
E         -         'credit_msat': Decimal('15579000.00000000'),
E         -         'debit_msat': 0,
E         -         'extra_tags': [],
E         -         'output_msat': Decimal('15579000.00000000'),
E         -         'primary_tag': 'deposit',
E         -         'utxo': '1b6fbf9887d6f9cce727fc8bf9f582a3353be682998d4bafc9691c9ed26897e7:0',
E         -     },
E         -     {
E         -         'account_id': '3ff8dfcfdab13f4f55f46af32334ae4f140ac5699b3661c9968347de8bad97c0',
E         -         'blockheight': 104,
E         -         'created_index': 7,
E                   'credit_msat': 0,
E                   'debit_msat': 49970073000,
E                   'extra_tags': [],
E                   'output_count': 5,
E                   'output_msat': 99970073000,
E                   'primary_tag': 'channel_close',
E                   'spending_txid': 'a499419bfdce179727cffca45429151db47839b247d83f71837429f021ae6322',
E                   'utxo': 'c097ad8bde478396c961369b69c50a144fae3423f36af4554f3fb1dacfdff83f:0',
E               },
E               {
E                   'account_id': 'external',
E                   'blockheight': 104,
E         -         'created_index': 8,
E         ?                          ^
E         +         'created_index': 6,
E         ?                          ^
E                   'credit_msat': 330000,
E                   'debit_msat': 0,
E                   'extra_tags': [],
E                   'originating_account': '3ff8dfcfdab13f4f55f46af32334ae4f140ac5699b3661c9968347de8bad97c0',
E                   'output_msat': 330000,
E                   'primary_tag': 'anchor',
E                   'utxo': 'a499419bfdce179727cffca45429151db47839b247d83f71837429f021ae6322:0',
E               },
E               {
E                   'account_id': 'external',
E                   'blockheight': 104,
E         -         'created_index': 9,
E         ?                          ^
E         +         'created_index': 7,
E         ?                          ^
E                   'credit_msat': 330000,
E                   'debit_msat': 0,
E                   'extra_tags': [],
E                   'originating_account': '3ff8dfcfdab13f4f55f46af32334ae4f140ac5699b3661c9968347de8bad97c0',
E                   'output_msat': 330000,
E                   'primary_tag': 'anchor',
E                   'utxo': 'a499419bfdce179727cffca45429151db47839b247d83f71837429f021ae6322:1',
E               },
E               {
E                   'account_id': 'external',
E                   'blockheight': 104,
E         -         'created_index': 10,
E         ?                          ^^
E         +         'created_index': 8,
E         ?                          ^
E                   'credit_msat': 50000000000,
E                   'debit_msat': 0,
E                   'extra_tags': [],
E                   'originating_account': '3ff8dfcfdab13f4f55f46af32334ae4f140ac5699b3661c9968347de8bad97c0',
E                   'output_msat': 50000000000,
E                   'primary_tag': 'to_them',
E                   'utxo': 'a499419bfdce179727cffca45429151db47839b247d83f71837429f021ae6322:4',
E               },
E           ]
```

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2026-01-08 22:33:19 +10:30
Rusty Russell
21d4f684f3 hsmd: check *all* anchor inputs for short sigs.
Anchors will have one input from the commitment tx, and at least on
more (in this case, 3 more); we were only checking the first one for
short signatures.

```
            total_feerate_perkw = total_fees / total_weight * 1000
>           check_feerate([l3, l2], total_feerate_perkw, feerate)

tests/test_closing.py:4064: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

nodes = [<fixtures.LightningNode object at 0x7f3e9a2c74f0>, <fixtures.LightningNode object at 0x7f3e991d5f30>]
actual_feerate = 14006.105538595726, expected_feerate = 14000

    def check_feerate(nodes, actual_feerate, expected_feerate):
        # Feerate can't be lower.
        assert actual_feerate > expected_feerate - 2
        if actual_feerate >= expected_feerate + 2:
            if any([did_short_sig(n) for n in nodes]):
                return
        # Use assert as it shows the actual values on failure
>       assert actual_feerate < expected_feerate + 2
E       AssertionError
```

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2026-01-08 22:33:19 +10:30
Rusty Russell
eb19862894 lightningd: don't complain if gossipd tells us about dead channel on startup.
This can happen if gossipd hasn't processed the blocks yet:

```
lightningd-2 2026-01-07T06:05:19.430Z **BROKEN** 0266e4598d1d3c415f572a8488830b60f7e744ed9235eb0b1ba93283b315c03518-chan#3: gossipd gave channel_update in CGOSSIP_CHANNEL_ANNOUNCED_DEAD? update=010240d5d1b653118c047218802d8c5d6bda49124fc9e1cb30ceff72e24c44e6a20d0b6b6fbe5465def31a01c8ff49dc171542a64a1a69d5149698f31e1ba4e721c106226e46111a0b59caaf126043eb5bbf28c34f3a5e332a1fc7b2b73cf188910f00006f0000010000695df63a010200060000000000000000000000010000000a000000003b023380
```

It does catch up later, so ignore this.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2026-01-08 22:33:19 +10:30
Rusty Russell
2333f024d3 pytest: work around pay flakiness.
pay sometimes ignores exclusions.  WONTFIX.

```
        with pytest.raises(RpcError, match=r'is not reachable directly and all routehints were unusable.'):
>           l1.rpc.pay(inv, exclude=[scid12])

tests/test_pay.py:5279: 
...
        elif "error" in resp:
>           raise RpcError(method, payload, resp['error'])
E           pyln.client.lightning.RpcError: RPC call failed: method: pay, payload: {'bolt11': 'lnbcrt1230n1p54mma3sp5x7uerjgyg7ws6fnzdwxc7pgpj6j25uhpqp5uvx3fk8dkcqm37m2spp5k02racjc9knux958u5rgtva24jfvxtr5w3t53pfeavn3thmyny0qdq8v3jhxccxqyjw5qcqp9rzjqgkjyd3q5dv6gllh77kygly9c3kfy0d9xwyjyxsq2nq3c83u5vw4jqqqvuqqqqgqqqqqqqqpqqqqqzsqqc9qxpqysgqcmv875mmzcjl8mwxxndy9an6p870ffpdxdtypmgf5gzsydnt2d68n4kjph0rcprye6tfz0ex0c5clgj3zwm8jgd5vs0fdv7hf7dqr8cqdrg3gf', 'exclude': ['103x2x0/1']}, error: {'code': 210, 'message': 'Ran out of routes to try after 6 attempts: see `paystatus`', 'attempts': [{'status': 'failed', 'failreason': 'No path found', 'partid': 0, 'amount_msat': 123000}, {'status': 'pending', 'failreason': 'No path found', 'partid': 1, 'amount_msat': 123000, 'parent_partid': 0}, {'status': 'failed', 'failreason': 'No path found', 'partid': 2, 'amount_msat': 57006, 'parent_partid': 1}, {'status': 'failed', 'failreason': 'No path found', 'partid': 4, 'amount_msat': 57006, 'parent_partid': 2}, {'status': 'failed', 'failreason': 'No path found', 'partid': 3, 'amount_msat': 65994, 'parent_partid': 1}, {'status': 'failed', 'failreason': 'No path found', 'partid': 5, 'amount_msat': 65994, 'parent_partid': 3}]}
```

The logs show that it doesn't exclude the routehint early: in successful runs we get "After filtering routehints we're left with 0 usable hints".  Perhaps this is something to do with the timing of our own notifications?

```
2026-01-07T05:51:10.7902502Z lightningd-1 2026-01-07T05:31:29.706Z DEBUG   plugin-pay: cmd -c:pay#64/cln:pay#121 partid 0: Received getchaininfo blockcount=108, headercount=108
2026-01-07T05:51:10.7903334Z lightningd-1 2026-01-07T05:31:29.715Z DEBUG   plugin-pay: cmd -c:pay#64/cln:pay#121 partid 0: waitblockheight reports syncheight=108
2026-01-07T05:51:10.7904256Z lightningd-1 2026-01-07T05:31:29.734Z DEBUG   plugin-pay: cmd -c:pay#64/cln:pay#121 partid 0: Updated a channel hint for 103x2x0/1: enabled true, estimated capacity 978718000msat
2026-01-07T05:51:10.7905355Z lightningd-1 2026-01-07T05:31:29.734Z DEBUG   plugin-pay: cmd -c:pay#64/cln:pay#121 partid 0: Updated a channel hint for 7269357x11669990x33910/1: enabled false, estimated capacity UNKNOWN
2026-01-07T05:51:10.7906580Z lightningd-1 2026-01-07T05:31:29.735Z DEBUG   plugin-pay: cmd -c:pay#64/cln:pay#121 partid 0: Updated a channel hint for 103x2x0/1: enabled false, estimated capacity UNKNOWN
2026-01-07T05:51:10.7907665Z lightningd-1 2026-01-07T05:31:29.735Z INFO    plugin-pay: cmd -c:pay#64/cln:pay#121 partid 0: Payment fee constraint 615msat is below exemption threshold, allowing a maximum fee of 5000msat
2026-01-07T05:51:10.7908845Z lightningd-1 2026-01-07T05:31:29.752Z DEBUG   plugin-pay: Received a channel_hint {.scid = 103x2x0/1, .enabled = 1, .estimate = 978718000msat, .capacity = 1000000000msat }
2026-01-07T05:51:10.7909710Z lightningd-1 2026-01-07T05:31:29.754Z INFO    plugin-pay: cmd -c:pay#64/cln:pay#121 partid 0: Filtering out 1 routehints
2026-01-07T05:51:10.7910544Z lightningd-1 2026-01-07T05:31:29.779Z DEBUG   plugin-pay: cmd -c:pay#64/cln:pay#121 partid 0: Checking hint {.scid=103x2x0/1, .enabled=1, .estimate=978718000msat}
2026-01-07T05:51:10.7911470Z lightningd-1 2026-01-07T05:31:29.780Z DEBUG   plugin-pay: cmd -c:pay#64/cln:pay#121 partid 0: After filtering routehints we're left with 1 usable hints
2026-01-07T05:51:10.7912385Z lightningd-1 2026-01-07T05:31:29.780Z DEBUG   plugin-pay: cmd -c:pay#64/cln:pay#121 partid 0: Checking hint {.scid=103x2x0/1, .enabled=1, .estimate=978718000msat}
2026-01-07T05:51:10.7913471Z lightningd-1 2026-01-07T05:31:29.780Z DEBUG   plugin-pay: cmd -c:pay#64/cln:pay#121 partid 0: Using routehint 022d223620a359a47ff7f7ac447c85c46c923da53389221a0054c11c1e3ca31d59 (103x1x0) cltv_delta=6
```

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2026-01-08 22:33:19 +10:30
Rusty Russell
55f8d049e1 pytest: mark reckless install test flaky.
Sometimes it times out under CI, but running 100 times here reveals
nothing.  Assume network issues and mark it flaky.

```
node_factory = <pyln.testing.utils.NodeFactory object at 0x7f6e700b8970>

    @pytest.mark.slow_test
    def test_reckless_uv_install(node_factory):
        node = get_reckless_node(node_factory)
        node.start()
>       r = reckless([f"--network={NETWORK}", "-v", "install", "testpluguv"],
                     dir=node.lightning_dir)

tests/test_reckless.py:358: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
tests/test_reckless.py:141: in reckless
    r = subprocess.run(cmds, capture_output=True, encoding='utf-8', env=my_env,
/opt/hostedtoolcache/Python/3.10.19/x64/lib/python3.10/subprocess.py:505: in run
    stdout, stderr = process.communicate(input, timeout=timeout)
/opt/hostedtoolcache/Python/3.10.19/x64/lib/python3.10/subprocess.py:1154: in communicate
    stdout, stderr = self._communicate(input, endtime, timeout)
/opt/hostedtoolcache/Python/3.10.19/x64/lib/python3.10/subprocess.py:2022: in _communicate
    self._check_timeout(endtime, orig_timeout, stdout, stderr)
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <Popen: returncode: -9 args: ['tools/reckless', '-l', '/tmp/ltests-kr4cjtd8/...>
endtime = 4623.246515403, orig_timeout = 60
stdout_seq = [b'[2026-01-07 05:55:15,159] DEBUG: Warning: Reckless requires write access\n[2026-01-07 05:55:15,159] DEBUG: Searching for testpluguv\n', b'[2026-01-07 05:55:15,179] DEBUG: InstInfo(testpluguv, https://github.com/lightningd/plugins, None, None, None, testpluguv), Source.GITHUB_REPO\nfound testpluguv in source: https://github.com/lightningd/plugins\n[2026-01-07 05:55:15,179] DEBUG: entry: None\n[2026-01-07 05:55:15,179] DEBUG: sub-directory: testpluguv\n[2026-01-07 05:55:15,179] DEBUG: Retrieving testpluguv from https://github.com/lightningd/plugins\n[2026-01-07 05:55:15,179] DEBUG: Install requested from InstInfo(testpluguv, https://github.com/lightningd/plugins, None, None, None, testpluguv).\n', b'cloning Source.GITHUB_REPO InstInfo(testpluguv, https://github.com/lightningd/plugins, None, None, None, testpluguv)\n[2026-01-07 05:55:15,405] DEBUG: cloned_src: InstInfo(testpluguv, /tmp/reckless-433081020a3dff932/clone, None, testpluguv.py, uv.lock, testpluguv/testpluguv)\n', b'[2026-01-07 05:55:15,409] DEBUG: using latest commit of default branch\n', b'[2026-01-07 05:55:15,417] DEBUG: checked out HEAD: 095457638f8080cd614a81cb4ad1cba7883549e3\n[2026-01-07 05:55:15,417] DEBUG: using installer pythonuv\n[2026-01-07 05:55:15,417] DEBUG: creating /tmp/ltests-kr4cjtd8/test_reckless_uv_install_1/lightning-1/reckless/testpluguv\n[2026-01-07 05:55:15,418] DEBUG: creating /tmp/ltests-kr4cjtd8/test_reckless_uv_install_1/lightning-1/reckless/testpluguv/source\n[2026-01-07 05:55:15,418] DEBUG: copying /tmp/reckless-433081020a3dff932/clone/testpluguv/testpluguv tree to /tmp/ltests-kr4cjtd8/test_reckless_uv_install_1/lightning-1/reckless/testpluguv/source/testpluguv\n[2026-01-07 05:55:15,419] DEBUG: linking source /tmp/ltests-kr4cjtd8/test_reckless_uv_install_1/lightning-1/reckless/testpluguv/source/testpluguv/testpluguv.py to /tmp/ltests-kr4cjtd8/test_reckless_uv_install_1/lightning-1/reckless/testpluguv/testpluguv.py\n[2026-01-07 05:55:15,419] DEBUG: InstInfo(testpluguv, /tmp/ltests-kr4cjtd8/test_reckless_uv_install_1/lightning-1/reckless/testpluguv, None, testpluguv.py, uv.lock, source/testpluguv)\n']
stderr_seq = [b'config file not found: /tmp/ltests-kr4cjtd8/test_reckless_uv_install_1/lightning-1/liquid-regtest/config\npress [Y] to create one now.\nconfig file not found: /tmp/ltests-kr4cjtd8/test_reckless_uv_install_1/lightning-1/reckless/liquid-regtest-reckless.conf\nconfig file not found: /tmp/ltests-kr4cjtd8/test_reckless_uv_install_1/lightning-1/reckless/.sources\n']
skip_check_and_raise = False

    def _check_timeout(self, endtime, orig_timeout, stdout_seq, stderr_seq,
                       skip_check_and_raise=False):
        """Convenience for checking if a timeout has expired."""
        if endtime is None:
            return
        if skip_check_and_raise or _time() > endtime:
>           raise TimeoutExpired(
                    self.args, orig_timeout,
                    output=b''.join(stdout_seq) if stdout_seq else None,
                    stderr=b''.join(stderr_seq) if stderr_seq else None)
E           subprocess.TimeoutExpired: Command '['tools/reckless', '-l', '/tmp/ltests-kr4cjtd8/test_reckless_uv_install_1/lightning-1', '--network=liquid-regtest', '-v', 'install', 'testpluguv']' timed out after 60 seconds
```

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2026-01-08 22:33:19 +10:30
Rusty Russell
04ad660cfa pytest: mark test_connection.py::test_disconnect_opener flaky.
It's a real bug, which I've reported in 

	https://github.com/ElementsProject/lightning/issues/8822

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2026-01-08 22:33:19 +10:30
Rusty Russell
749f504071 pytest: fix flake race in test_even_sendcustommsg.
It failed, because it got the message before connectd has processed
the updated allow list:

```
lightningd-2 2026-01-06T07:53:02.817Z INFO    plugin-allow_even_msgs.py: Killing plugin: stopped by lightningd via RPC
...
lightningd-1 2026-01-06T07:53:02.820Z DEBUG   022d223620a359a47ff7f7ac447c85c46c923da53389221a0054c11c1e3ca31d59-lightningd: sendcustommsg id="-c:sendcustommsg#16" sending a custom even message (43690)
...
lightningd-1 2026-01-06T07:53:02.820Z 022d223620a359a47ff7f7ac447c85c46c923da53389221a0054c11c1e3ca31d59-connectd: [OUT] aaaaffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffbb
lightningd-2 2026-01-06T07:53:02.823Z 0266e4598d1d3c415f572a8488830b60f7e744ed9235eb0b1ba93283b315c03518-connectd: [IN] aaaaffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffbb
...
lightningd-2 2026-01-06T07:53:02.823Z DEBUG   connectd: Now allowing 0 custom message types
```

Resulting in:

``
        l2.daemon.wait_for_log(r'\[IN\] {}'.format(msg))
>       l1.daemon.wait_for_log('Invalid unknown even msg')

tests/test_misc.py:4673: 
...
>                   raise TimeoutError('Unable to find "{}" in logs.'.format(exs))
E                   TimeoutError: Unable to find "[re.compile('Invalid unknown even msg')]" in logs.
```

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2026-01-08 22:33:19 +10:30
Rusty Russell
bb4d8cdb06 lightningd: fix error code on waitsendpay on old errors.
We don't explicitly save the return code in db, so we need to reconstruct it.

We didn't cover the "peer told us our onion was bad" corner case.  But it's hardly
worth a changelog message, since users will never see this.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2026-01-08 22:33:19 +10:30
Rusty Russell
17b447bc61 pytest: explicitly test failed case exposed by race.
This showed up as a flake, where we "got lucky" and the sendpay resolved before waitsendpay was called.  Instead, make this race explicit, so we can test it.

```
        # FIXME: #define PAY_UNPARSEABLE_ONION		202
        PAY_UNPARSEABLE_ONION = 202
>       assert err.value.error['code'] == PAY_UNPARSEABLE_ONION
E       assert 204 == 202

tests/test_misc.py:2152: AssertionError
```

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2026-01-08 22:33:19 +10:30
Rusty Russell
7971e6aa11 pytest: don't get upset at slow multi-input signing under valgrind.
```
2026-01-06T07:46:35.5710043Z lightningd-1 2026-01-06T07:45:11.040Z UNUSUAL jsonrpc#68: That's weird: Request signpsbt took 5099 milliseconds
```

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2026-01-08 22:33:19 +10:30
Rusty Russell
03025469be pay: don't notify using uninitialized hint field.
Rather than break the API, use total capacity here.

```
Valgrind error file: valgrind-errors.5880
==5880== Use of uninitialised value of size 8
==5880==    at 0x4A390BB: _itoa_word (_itoa.c:183)
==5880==    by 0x4A43C9B: __printf_buffer (vfprintf-process-arg.c:155)
==5880==    by 0x4A69D90: vsnprintf (vsnprintf.c:96)
==5880==    by 0x1875E6: json_out_addv (json_out.c:239)
==5880==    by 0x14471E: json_add_primitive_fmt (json_stream.c:170)
==5880==    by 0x144BA2: json_add_u64 (json_stream.c:282)
==5880==    by 0x145E33: json_add_amount_msat (json_stream.c:619)
==5880==    by 0x11DDE2: channel_hint_to_json (channel_hint.c:33)
==5880==    by 0x11FE9F: channel_hint_notify_core (libplugin-pay.c:394)
==5880==    by 0x11FF7A: channel_hint_notify (libplugin-pay.c:412)
==5880==    by 0x1201EA: channel_hints_update (libplugin-pay.c:455)
==5880==    by 0x122DAF: handle_intermediate_failure (libplugin-pay.c:1437)
==5880== 
```

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2026-01-08 22:33:19 +10:30
Rusty Russell
94e3c1502f pytest: reduce test_funding_v2_cancel_race nodes under CI.
```
[gw0] [ 24%] PASSED tests/test_misc.py::test_hsm_capabilities 
tests/test_connection.py::test_funding_cancel_race 
Error: Process completed with exit code 143.
```

Seems like 100 nodes is too many!

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2026-01-08 22:33:19 +10:30
Rusty Russell
082e70aada pytest: make sure node order is stable before querying in test_gossmap_lost_node
The channel vanishes from listchannels when it's dying, *but* only when it gets deleted
do we consider moving the actual node_announcement.  We have to wait until gossipd
has seen the 12 blocks, and move it if necessary.

```
E         Full diff:
E           {
E               'nodes': [
E         -         {
E         -             'addresses': [],
E         -             'alias': 'SILENTARTIST-e986cd2-modded',
E         -             'color': '022d22',
E         -             'features': '808898880a8a59a1',
E         -             'last_timestamp': 1767572731,
E         -             'nodeid': '022d223620a359a47ff7f7ac447c85c46c923da53389221a0054c11c1e3ca31d59',
E         -         },
E                   {
E                       'addresses': [],
E                       'alias': 'HOPPINGFIRE-e986cd2-modded',
E                       'color': '035d2b',
E                       'features': '808898880a8a59a1',
E                       'last_timestamp': 1767572731,
E                       'nodeid': '035d2b1192dfba134e10e540875d366ebc8bc353d5aa766b80c090b39c3a5d885d',
E                   },
E                   {
E                       'addresses': [],
E                       'alias': 'JUNIORFELONY-e986cd2-modded',
E                       'color': '0382ce',
E                       'features': '808898880a8a59a1',
E                       'last_timestamp': 1767572731,
E                       'nodeid': '0382ce59ebf18be7d84677c2e35f23294b9992ceca95491fcf8a56c6cb2d9de199',
E                   },
E                   {
E                       'addresses': [],
E         +             'alias': 'SILENTARTIST-e986cd2-modded',
E         +             'color': '022d22',
E         +             'features': '808898880a8a59a1',
E         +             'last_timestamp': 1767572731,
E         +             'nodeid': '022d223620a359a47ff7f7ac447c85c46c923da53389221a0054c11c1e3ca31d59',
E         +         },
E         +         {
E         +             'addresses': [],
E                       'alias': 'JUNIORBEAM-e986cd2-modded',
E                       'color': '0266e4',
E                       'features': '808898880a8a59a1',
E                       'last_timestamp': 1767572732,
E                       'nodeid': '0266e4598d1d3c415f572a8488830b60f7e744ed9235eb0b1ba93283b315c03518',
E                   },
E               ],
E           }

tests/test_gossip.py:2390: AssertionError
```

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2026-01-08 22:33:19 +10:30
Rusty Russell
7175001988 pytest: get more\ information when test_funding_v2_cancel_race fails.
```
2026-01-05T00:11:22.0447771Z             # Only up to one should succeed.
2026-01-05T00:11:22.0448201Z             success = False
2026-01-05T00:11:22.0448571Z             for c in completes:
2026-01-05T00:11:22.0448957Z                 try:
2026-01-05T00:11:22.0449322Z                     c.result(TIMEOUT)
2026-01-05T00:11:22.0449934Z                     num_complete += 1
2026-01-05T00:11:22.0450378Z >                   assert not success
2026-01-05T00:11:22.0451005Z E                   assert not True
2026-01-05T00:11:22.0451201Z 
2026-01-05T00:11:22.0451331Z tests/test_connection.py:1596: AssertionError
```

We don't know *which* ones succeeded.  Fix that.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2026-01-08 22:33:19 +10:30
Rusty Russell
72c841ef34 pytest: fix flake if rune tests are slow.
If one second has passed during testing, checkrune might pass:

```
        # default (sec)
        rune_per_default = l1.rpc.createrune(restrictions=[["per=1"]])['rune']
        assert rune_per_default == 'NrM7go6C4qzfRQDkUSv1DtRroJWSKqdjIOuvGS4TLFE9NCZwZXI9MQ=='
>       do_test_rune_per_restriction(l1, rune_per_default, 1)

tests/test_runes.py:269: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

l1 = <fixtures.LightningNode object at 0x7f7344ad2ef0>
rune_to_test = 'NrM7go6C4qzfRQDkUSv1DtRroJWSKqdjIOuvGS4TLFE9NCZwZXI9MQ=='
per_sec = 1

    def do_test_rune_per_restriction(l1, rune_to_test, per_sec):
...
        # cannot use same rune till 'per_sec' seconds
>       with pytest.raises(RpcError, match='Not permitted:') as exc_info:
E       Failed: DID NOT RAISE <class 'pyln.client.lightning.RpcError'>

tests/test_runes.py:217: Failed
```

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2026-01-08 22:33:19 +10:30
Rusty Russell
1741e166a6 lightningd: fix occasional memleak when we detach subd from channel.
Do this by setting notleak when we do the detach!

```
**BROKEN** lightningd: MEMLEAK: 0x60f0000bbb38
**BROKEN** lightningd:   label=ccan/ccan/io/io.c:92:struct io_conn
**BROKEN** lightningd:   alloc:
**BROKEN** lightningd:     /home/runner/work/lightning/lightning/ccan/ccan/tal/tal.c:488 (tal_alloc_)
**BROKEN** lightningd:     /home/runner/work/lightning/lightning/ccan/ccan/io/io.c:92 (io_new_conn_)
**BROKEN** lightningd:     /home/runner/work/lightning/lightning/lightningd/subd.c:781 (new_subd)
**BROKEN** lightningd:     /home/runner/work/lightning/lightning/lightningd/subd.c:835 (new_channel_subd_)
**BROKEN** lightningd:     /home/runner/work/lightning/lightning/lightningd/channel_control.c:1715 (peer_start_channeld)
**BROKEN** lightningd:     /home/runner/work/lightning/lightning/lightningd/peer_control.c:1390 (connect_activate_subd)
**BROKEN** lightningd:     /home/runner/work/lightning/lightning/lightningd/peer_control.c:1516 (peer_connected_hook_final)
**BROKEN** lightningd:     /home/runner/work/lightning/lightning/lightningd/plugin_hook.c:243 (hook_done)
**BROKEN** lightningd:     /home/runner/work/lightning/lightning/lightningd/plugin_hook.c:343 (plugin_hook_call_next)
**BROKEN** lightningd:     /home/runner/work/lightning/lightning/lightningd/plugin_hook.c:299 (plugin_hook_callback)
**BROKEN** lightningd:     /home/runner/work/lightning/lightning/lightningd/plugin.c:701 (plugin_response_handle)
**BROKEN** lightningd:     /home/runner/work/lightning/lightning/lightningd/plugin.c:790 (plugin_read_json)
**BROKEN** lightningd:     /home/runner/work/lightning/lightning/ccan/ccan/io/io.c:60 (next_plan)
**BROKEN** lightningd:     /home/runner/work/lightning/lightning/ccan/ccan/io/io.c:422 (do_plan)
**BROKEN** lightningd:     /home/runner/work/lightning/lightning/ccan/ccan/io/io.c:439 (io_ready)
**BROKEN** lightningd:     /home/runner/work/lightning/lightning/ccan/ccan/io/poll.c:470 (io_loop)
**BROKEN** lightningd:     /home/runner/work/lightning/lightning/lightningd/io_loop_with_timers.c:22 (io_loop_with_timers)
**BROKEN** lightningd:     /home/runner/work/lightning/lightning/lightningd/lightningd.c:1492 (main)
**BROKEN** lightningd:     ../sysdeps/nptl/libc_start_call_main.h:58 (__libc_start_call_main)
**BROKEN** lightningd:     ../csu/libc-start.c:392 (__libc_start_main_impl)
**BROKEN** lightningd:   parents:
**BROKEN** lightningd:     lightningd/lightningd.c:108:struct lightningd
```

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2026-01-08 22:33:19 +10:30