Compare commits

..

1821 Commits

Author SHA1 Message Date
nicolas.dorier
d94b9a2713
Adapt Dockerfile for BTCPay deployment
Some checks failed
Docker packaging / main (push) Has been cancelled
2025-07-16 13:29:50 +09:00
Alex Myers
2b8b709bfd meta: update changelog for v25.05
Changelog-None
2025-06-16 13:10:33 -05:00
Alex Myers
acf935e1c8 github: Update release dates for 25.09
Changelog-None
2025-06-16 13:10:33 -05:00
Rusty Russell
f2f7b6e225 pytest: fix flake in test_anchorspend_using_to_remote
With recent changes, particularly using postgres, we can finish the HTLC before
we force close, so the test fails.  Insert an explicit hangup here so we reliably
get the result we expect:

```
    @pytest.mark.parametrize("anchors", [False, True])
    @unittest.skipIf(TEST_NETWORK != 'regtest', 'elementsd anchors not supportd')
    def test_anchorspend_using_to_remote(node_factory, bitcoind, anchors):
        """Make sure we can use `to_remote` output of previous close to spend anchor"""
        # Try with old output from both anchor and non-anchor channel.
        l4_opts = {}
        if anchors is False:
            l4_opts['dev-force-features'] = "-23"
    
        l1, l2, l3, l4 = node_factory.get_nodes(4, opts=[{},
                                                         {},
                                                         {'disconnect': ['-WIRE_UPDATE_FULFILL_HTLC']},
                                                         l4_opts])
    
        # Give l2 some funds, from a to-remote output.  It will have to spend
        # this to use anchor.
        node_factory.join_nodes([l4, l2])
    
        # l4 unilaterally closes, l2 gets to-remote with its output.
        l4.rpc.pay(l2.rpc.invoice(100000000, 'test', 'test')['bolt11'])
>       wait_for(lambda: only_one(l4.rpc.listpeerchannels()['channels'])['htlcs'] != [])

tests/test_closing.py:4183: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

success = <function test_anchorspend_using_to_remote.<locals>.<lambda> at 0x7f8293e7fe20>
timeout = 180

    def wait_for(success, timeout=TIMEOUT):
        start_time = time.time()
        interval = 0.25
        while not success():
            time_left = start_time + timeout - time.time()
            if time_left <= 0:
>               raise ValueError("Timeout while waiting for {}".format(success))
E               ValueError: Timeout while waiting for <function test_anchorspend_using_to_remote.<locals>.<lambda> at 0x7f8293e7fe20>

```

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2025-06-13 13:55:31 -05:00
Rusty Russell
6468d439e0 ccan: update for FreeBSD compile fixes.
Also gets some new timemono helpers, but we don't use them (yet).

Changelog-Fixed: Compilation on FreeBSD.
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
Closes: https://github.com/ElementsProject/lightning/issues/7758
2025-06-13 12:21:53 -05:00
Alex Myers
9d160eb8fb wallet: load closed channels at init
This seems to have been inadvertently omitted in the recent
closed channel refactor.

Fixes: #8346

Changelog-None: Changed this release.
2025-06-13 11:40:06 +09:30
daywalker90
40d319b7be python: raise minimum supported python version to 3.9
Changelog-None
2025-06-12 13:51:18 +02:00
Rusty Russell
03b4f4778e lightningd: fix log crash on weird escape lines from plugin.
Apparently clboss gives us \u UTF codes.  We don't support that (use UTF-8 directly)

```
126	../sysdeps/x86_64/multiarch/strlen-vec.S: No such file or directory.
(gdb) bt
    label=label@entry=0x63e2f9604db9 "char *[]") at ccan/ccan/tal/str/str.c:137
    complete=complete@entry=0x7ffe9090b0f6, destroyed=destroyed@entry=0x7ffe9090b0f7) at lightningd/plugin.c:773
```

Reported-by: Ken Sedgwick
Fixes: #8338
Changelog-None: broken in this release
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2025-06-11 08:50:34 -05:00
Rusty Russell
eddb0e3bbd CHANGELOG.md: warn that spec compliance mean we broke splicing.
The TLV numbers for splicing were used by the upgrade protocol, and we always
demarshal TLVs:

```
rusty@rusty-Framework:~/devel/cvs/lightning ((v25.02.1))$ ./devtools/decodemsg 00883d448f5a4d2d82c861a1e60ba317f5c848989d8c92f65833ff85cc82cb96adf500000000000000c600000000000000c559ebae46ed6f64c3e7c0005494bc684a630223d4b942a7e09b76742727b863cc02aac24eb41bbcfd77cb2e75f51bc5d298a6862cd7c2478268aa67572d8a08311801203d448f5a4d2d82c861a1e60ba317f5c848989d8c92f65833ff85cc82cb96adf503203d448f5a4d2d82c861a1e60ba317f5c848989d8c92f65833ff85cc82cb96adf5
WIRE_CHANNEL_REESTABLISH:
channel_id=3d448f5a4d2d82c861a1e60ba317f5c848989d8c92f65833ff85cc82cb96adf5
next_commitment_number=198
next_revocation_number=197
your_last_per_commitment_secret=59ebae46ed6f64c3e7c0005494bc684a630223d4b942a7e09b76742727b863cc
my_current_per_commitment_point=02aac24eb41bbcfd77cb2e75f51bc5d298a6862cd7c2478268aa67572d8a083118
channel_reestablish={
type=1
len=32
(msg_name=next_to_send)
commitment_number=**TRUNCATED tu64 channel_reestablish.channel_reestablish.commitment_number**
**TRUNCATED TLV channel_reestablish.channel_reestablish**
Segmentation fault (core dumped)
```

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
Closes: #8337
2025-06-11 08:15:56 -05:00
Matt Whitlock
3f6cd59dc9 gossipd: check for existing channel announcement before sigcheck
Checking a signature is a CPU-intensive operation that should be performed only
if gossmap doesn't already have the channel announcement in question and we're
not already checking for the announcement's UTxO.

Changelog-Fixed: `gossipd` doesn't waste CPU cycles checking signatures on channel announcements that are already known
Issue: https://github.com/ElementsProject/lightning/issues/7972
2025-06-10 16:40:33 -05:00
ShahanaFarooqui
ae320cd8d2 CI: Update Ubuntu version from 20 to 22 for Github Actions
Ubuntu 20.04 reached its end-of-life (EOL) on April 15, 2025, and GitHub Actions subsequently removed the Ubuntu 20.04 LTS runner. As a result, we must upgrade all workflow runners to at least Ubuntu 22.04. Currently, this update has only been applied to pypi.yml for core-lightning.

Changelog-None.
2025-06-09 14:24:53 -05:00
ShahanaFarooqui
ad2dc972de ci: Fix noble repro build by updating sqlite3 version and shasums
The reproducible build is currently failing on Ubuntu Noble, causing the daily `Repro Build Nightly` GitHub action to fail and triggering email notifications.

This update resolves the issue by adjusting the default sqlite3 version and checksums to match the packages now available in Noble, allowing the image to build successfully.

Changelog-None.
2025-06-05 17:38:55 -05:00
daywalker90
b97278fb9a python: upgrade grpcio-tools to 1.69.0 and protobuf to 5.29.4 for python3.13 compatibility
Changelog-None
2025-05-21 10:58:15 -05:00
Alex Myers
2c2fbe36e1 meta: update changelog for 25.05rc1 2025-05-19 14:12:55 -05:00
Alex Myers
8d6ae149ff release: update version for 25.05rc1
Changelog-None
2025-05-19 14:12:55 -05:00
Rusty Russell
f68feaeb37 pytest: fix races now connecting is slightly slower.
We asserted that a node would be connected, but now we always call the
chanbackup peer_connected hook, it might not be that fast:

```
2025-05-17T08:37:58.7193306Z     def test_funding_fail(node_factory, bitcoind):
...
2025-05-17T08:37:58.7204037Z         # Restart l2 without ridiculous locktime.
2025-05-17T08:37:58.7204546Z         del l2.daemon.opts['watchtime-blocks']
2025-05-17T08:37:58.7204990Z         l2.restart()
2025-05-17T08:37:58.7206578Z         l1.rpc.connect(l2.info['id'], 'localhost', l2.port)
2025-05-17T08:37:58.7207072Z     
2025-05-17T08:37:58.7207522Z         # We don't have enough left to cover fees if we try to spend it all.
2025-05-17T08:37:58.7208203Z         with pytest.raises(RpcError, match=r'not afford'):
2025-05-17T08:37:58.7208761Z             l1.rpc.fundchannel(l2.info['id'], funds)
2025-05-17T08:37:58.7209203Z     
2025-05-17T08:37:58.7209598Z         # Should still be connected (we didn't contact the peer)
2025-05-17T08:37:58.7210243Z         assert only_one(l1.rpc.listpeers()['peers'])['connected']
2025-05-17T08:37:58.7210875Z         l2.daemon.wait_for_log('Handed peer, entering loop')
2025-05-17T08:37:58.7211439Z >       assert only_one(l2.rpc.listpeers()['peers'])['connected']
2025-05-17T08:37:58.7211912Z E       assert False
```

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2025-05-17 13:05:04 -05:00
Rusty Russell
b15100d03a lightningd: don't complain when gossipd gives us channel_update for dying channel.
It can definitely happen (it's not dead yet):

```
2025-05-17T08:44:48.9829150Z lightningd-2 2025-05-17T08:36:43.597Z **BROKEN** 0266e4598d1d3c415f572a8488830b60f7e744ed9235eb0b1ba93283b315c03518-chan#3: gossipd gave channel_update in CGOSSIP_CHANNEL_ANNOUNCED_DYING? update=01027cf5d46590c45eb608a7e07a7b123c998ac12a655ce11004c9d9bb59f83698e8760d7b992df0dcf925f6732503de55d596aadaa35f0a8837cee58e0769172d2a06226e46111a0b59caaf126043eb5bbf28c34f3a5e332a1fc7b2b73cf188910f00006f00000100006828493f010200060000000000000000000000010000000a000000003b023380
```

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2025-05-17 13:05:04 -05:00
Rusty Russell
04ba55d88b wallet: fix incorrect channel_htlcs id migration.
We were supposed to initialize `last_htlcs_created_index` but a typo
made us initialize `last_forwards_created_index` instead.  Fix up the
overwritten one, and actually initialize the one we were supposed to.

Fixes: https://github.com/ElementsProject/lightning/issues/8269
Fixes: https://github.com/ElementsProject/lightning/issues/8270
Changelog-None: recently introduced bug
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2025-05-17 13:05:04 -05:00
Rusty Russell
1cc64dd67c pytest: test to crash on migration from old db.
```
Error executing statement: wallet/wallet.c:3247: INSERT INTO channel_htlcs ( id, channel_id, channel_htlc_id, direction, origin_htlc, msatoshi, cltv_expiry, payment_hash, payment_key, hstate, routing_onion, malformed_onion, partid, groupid, fees_msat, min_commit_num) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, 0, ?, ?, ?, ?);: UNIQUE constraint failed: channel_htlcs.id
lightningd: FATAL SIGNAL 6 (version v25.02-321-g3999879)
0x642e42dc974f send_backtrace
	common/daemon.c:33
0x642e42dc97eb crashdump
	common/daemon.c:78
0x7d90f2e4532f ???
	./signal/../sysdeps/unix/sysv/linux/x86_64/libc_sigaction.c:0
0x7d90f2e9eb2c __pthread_kill_implementation
	./nptl/pthread_kill.c:44
0x7d90f2e9eb2c __pthread_kill_internal
	./nptl/pthread_kill.c:78
0x7d90f2e9eb2c __GI___pthread_kill
	./nptl/pthread_kill.c:89
0x7d90f2e4527d __GI_raise
	../sysdeps/posix/raise.c:26
0x7d90f2e288fe __GI_abort
	./stdlib/abort.c:79
0x642e42d71f79 fatal_vfmt
	lightningd/log.c:1055
0x642e42da61e8 db_error
	wallet/db.c:1117
0x642e42e1eafc db_fatal
	db/utils.c:323
0x642e42e1eee6 db_exec_prepared_v2
	db/utils.c:197
0x642e42db1fd9 wallet_htlc_save_out
	wallet/wallet.c:3310
0x642e42d8f07f update_out_htlc
	lightningd/peer_htlcs.c:1978
0x642e42d8f435 changed_htlc
	lightningd/peer_htlcs.c:2011
0x642e42d929aa peer_sending_commitsig
	lightningd/peer_htlcs.c:2108
0x642e42d5002f channel_msg
	lightningd/channel_control.c:1533
0x642e42d9ec3a sd_msg_read
	lightningd/subd.c:560
0x642e42e88435 next_plan
	ccan/ccan/io/io.c:60
0x642e42e88906 do_plan
	ccan/ccan/io/io.c:422
0x642e42e889c3 io_ready
	ccan/ccan/io/io.c:439
0x642e42e8a332 io_loop
	ccan/ccan/io/poll.c:455
0x642e42d69b01 io_loop_with_timers
	lightningd/io_loop_with_timers.c:22
0x642e42d6f525 main
	lightningd/lightningd.c:1486
0x7d90f2e2a1c9 __libc_start_call_main
	../sysdeps/nptl/libc_start_call_main.h:58
0x7d90f2e2a28a __libc_start_main_impl
	../csu/libc-start.c:360
0x642e42d41b64 ???
	???:0
0xffffffffffffffff ???
```

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2025-05-17 13:05:04 -05:00
Rusty Russell
44972b2e15 chanbackup: unbias our random peer selection.
We picked one node and iterated.  This means we would only sent to 1,
not 2 nodes if we picked the last (common if there were only a few
peers).  But it also means we would generally send to the same pair of
nodes, which isn't great for redundancy.

Rework to be more random.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2025-05-16 23:39:35 +09:30
Rusty Russell
b7e20b327c lightningd: enable peer storage by default,
Now we've make it only on existing channels, and not have to call
listdatastore every time, that means we can safely turn it on by
default.

Changelog-Added: Protocol: we now offer peer storage to any peers who create a channel.
Changelog-Deprecated: Config: `--experimental-peer-storage` (it's now the default).
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2025-05-16 23:39:35 +09:30
Rusty Russell
40dfbcc124 pytest: make test_v2_rbf_liquidity_ad more robust against other datastore users.
When peer backup is enabled by default, it puts things in the datastore, breaking
this assumption.  Narrow the test to examine the specific funder directory.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2025-05-16 23:39:35 +09:30
Rusty Russell
49ccb0eeb8 chanbackup: don't send our backups to peers if they would be overlength.
They will in fact get truncated, and never restore.  Large nodes should be using some real
backup strategy!

For this reason, we split "peer_backup" support into send vs store support, so we can
turn off send of our own without disabling storing/sending theirs.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2025-05-16 23:39:35 +09:30
Rusty Russell
c5cde13af6 chanbackup: only send channel backups to max 2 peers at a time.
This, too, is vital for large nodes, which don't want a significant
traffic increase.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2025-05-16 23:39:35 +09:30
Rusty Russell
90bbd8aedc chanbackup: use peer table instead of calling "listpeerchannels".
This is much better for very large nodes with lots of channel activity.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2025-05-16 23:39:35 +09:30
Rusty Russell
4eafc1a2e1 chanbackup: cache available peers.
We already get the connected hook, so in there we can add to a hash
table of suitable peers.  Rather than subscribe to disconnection, we
simply remove the peer if a sendcustommsg fails.

This does make after_send_scb_single() a bit more complex, since it
needs this specific node_id: we use a `struct info` per node and a
pointer to a shared "idx" reference counter.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2025-05-16 23:39:35 +09:30
Rusty Russell
bda52c315c chanbackup: use the cache instead of calling listdatastore every time.
Now actually use our cache.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2025-05-16 23:39:35 +09:30
Rusty Russell
dc2c3668e6 chanbackup: use local memory to store peer backups.
By keeping a local hash table, we won't have to look up every time.
We still write to the datastore when it changes, and we need to
initialize it at plugin start.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2025-05-16 23:39:35 +09:30
Rusty Russell
2d821d6012 libplugin: fix jsonrpc_set_datastore_binary/jsonrpc_set_datastore_string with NULL cb.
This should complete the command, otherwise we get an assertion on
line 1090.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2025-05-16 23:39:35 +09:30
Rusty Russell
adf7663fef chanbackup: only store backups for peers with current/previous channels.
This seems fair.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2025-05-16 23:39:35 +09:30
Rusty Russell
cdce113d57 chanbackup: use modern plugin_data.
This avoids globals, which is a bit neater.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2025-05-16 23:39:35 +09:30
Rusty Russell
f590962be2 chanbackup: less logging in preparation for default enable.
We should not send a message on unknown custom message receipt (we
expect this!).

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2025-05-16 23:39:35 +09:30
Rusty Russell
e8690021ee chanbackup: remove unnecessary allocation.
after_listpeers() doesn't use the argument, so we don't need to allocate anything.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2025-05-16 23:39:35 +09:30
Rusty Russell
9357954bd9 chanbackup: add spec quotes now we have this in the spec.
This is the only way to track spec changes in future.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2025-05-16 23:39:35 +09:30
Rusty Russell
f5b6b6f8cf pytest: fix flake in test_gossip_force_broadcast_channel_msgs caused by ping timeout.
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2025-05-16 22:40:45 +09:30
Rusty Russell
72a8fa20f7 gossipwith: add --handle-pings flag.
Required for long gossips, where we might get timed out for not replying to pings.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2025-05-16 22:40:45 +09:30
Rusty Russell
40a86daaf5 lightningd: fix crash in "shouldn't happen" path.
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2025-05-16 22:40:45 +09:30
Erick Cestari
9b662a83e7 common/bolt11: validate public keys in routing hints
Changelog-Fixed: Validated public keys in BOLT11 routing hints to
prevent processing of malformed public keys.
2025-05-16 14:37:52 +09:30
Dusty Daemon
10708e3168 splice: Adjust batch_size TLV to match Eclair’s
Eclair only sets `batch_size` and `funding_txid` when its a batch larger than 1.

Adjust how we send and what we expect to receive to match this.

Changelog-None
2025-05-15 16:58:00 -05:00
daywalker90
529337a5fb msggen: add signmessagewithkey
Changelog-None
2025-05-15 13:04:13 +02:00
Rusty Russell
8494ca608a pytest: fix flake in test_peer_anchor_push
If l3 does a short signature, our feerate will also be wrong.  Adjust
check_feerate to take a range of nodes for this case.

```
>           check_feerate(l2, total_feerate_perkw, feerate)

tests/test_closing.py:4054: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

node = <fixtures.LightningNode object at 0x7fd7e2cbfb20>
actual_feerate = 14006.105538595726, expected_feerate = 14000

    def check_feerate(node, actual_feerate, expected_feerate):
        # Feerate can't be lower.
        assert actual_feerate > expected_feerate - 2
        if not did_short_sig(node):
>           assert actual_feerate < expected_feerate + 2
E           AssertionError

tests/utils.py:675: AssertionError
```
2025-05-15 17:20:07 +09:30
Rusty Russell
3a0a02c406 pytest: fix case where test can do unilateral close
And we timeout in:

    l2.wait_for_channel_onchain(l1.info['id'])

Because the unilateral wins.  This is because we tell closingd to
negotiate with a min feerate of 3750, but when it does and we check it,
our min has jumped, lightningd rejects it:

	... That's below our min XXX for weight 772 at feerate 7000

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2025-05-15 17:20:07 +09:30
Rusty Russell
01a8d2b01a lightningd: send announcement_signatures once channel is ready, don't wait until 6 deep.
The spec used to say you had to wait for channel to be ready, *and* 6
depth before exchanging signatures.  Now the 6 depth requirement is only
on the actual announcing of the channel: you can send sigs any time.

This means our state machine goes from:

  NOT_USABLE -> NOT_DEEP_ENOUGH -> NEED_PEER_SIGS -> ANNOUNCED

to:

  NOT_USABLE -> NEED_PEER_SIGS -> NOT_DEEP_ENOUGH -> ANNOUNCED

However, this revealed that our state machine is insufficient, so
rework it to be more general and understandable.  In particular,
check for unexpected state transitions, and thus document them.

Note that cg->sent_sigs replaces channel->replied_to_announcement_sigs,
too.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
Changelog-Changed: Protocol: We now exchange `announcement_signatures` as soon as we're ready, rather than waiting for 6 blocks (as per recent BOLT update)
2025-05-15 16:40:33 +09:30
Rusty Russell
167767d683 lightningd: don't hand redundant block_height to block notifications.
They can all call get_block_height(); the extra argument confused me and
I thought they were called before the block height was actually updated.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2025-05-15 16:40:33 +09:30
Rusty Russell
6b77c95b95 gossipd: don't spam the log on duplicate channel_update.
This message was too verbose (even for trace!)

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2025-05-15 16:40:33 +09:30
Rusty Russell
6860cd9cd4 lightningd: split channel update creation functions.
We want a more fine-grained approach, so we now have:

1. update_channel_update() - returns true if it changed.
2. channel_should_enable() - should this channel be marked enabled.
3. arm_refresh_timer() - start a refresh timer for the channel_update.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2025-05-15 16:40:33 +09:30
Rusty Russell
9c1c2f687b lightningd: add another stae check function.
In this case a "are we closed onchain".

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2025-05-15 16:40:33 +09:30
Rusty Russell
e11c2f6c04 channeld: allow announcement_signatures during splice.
It can actually happen, at least in theory.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2025-05-15 16:40:33 +09:30
Rusty Russell
cca6d166c6 closingd: ignore announcement_signatures during closing.
This could always happen, but now we're more correct about send it, it's
a possible race that I've seen in CI.

We can never get a PONG (that's now handled by connectd directly), but we
can definitely see this:

```
2025-05-15T02:29:14.7403081Z         # Even with onchain anchor channel, it still keeps reserve (just in case!).
2025-05-15T02:29:14.7403766Z >       l1.rpc.close(l2.info['id'])
2025-05-15T02:29:14.7404069Z 
2025-05-15T02:29:14.7404248Z tests/test_opening.py:2536:
...
2025-05-15T02:29:14.7413090Z >       return self.sock.recv(length)
2025-05-15T02:29:14.7413353Z E       Failed: Timeout >1800.0s
...
2025-05-15T02:29:14.8097229Z lightningd-1 2025-05-15T01:50:59.538Z DEBUG   022d223620a359a47ff7f7ac447c85c46c923da53389221a0054c11c1e3ca31d59-closingd-chan#1: billboard perm: Expected closing_signed: 0103fad81b49d5e367cd785e3088b9acf356a7984a17a1ccda86d09da41438840b08000067000001000078c3314666731e339c0b8434f7824797a084ed7ca3655991a672da068e2c44cb53b57b53a296c133bc879109a8931dc31e6913a4bda3d58559b99b95663e6d52679cabaccc6e39dbd95a4dac90e75a258893c3aa3f733d1b8890174d5ddea8003cadffe557773c54d2c07ca1d535c4bf85885f879ae466c16a516e8ffcfec174
```

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2025-05-15 16:40:33 +09:30
Rusty Russell
53a67b6a86 lightningd: rename anchor_confirms to funding_confirms.
Calling the funding tx an anchor is pre-spec terminology, which is now
confusing; let's rename the variable.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2025-05-15 16:40:33 +09:30
Matt Whitlock
f816393095 Makefile: escape single-quotes in VERBOSE $(ECHO) argument
When the command string run through $(call VERBOSE,…) contains a single-quote
character followed by shell metacharacters, the shell executing the VERBOSE
template's $(ECHO) command will attempt to interpret those metacharacters. This
could be disastrous, such as if someone were to put in a Makefile recipe:

	$(call VERBOSE, , $(ECHO) 'Will not `rm -rf ~`')

When run with V=1, which causes VERBOSE to be defined as…

	VERBOSE = $(ECHO) '$(2)'; $(2)

…Make would evaluate the above call into:

	echo 'echo 'Will not `rm -rf ~`''; echo 'Will not `rm -rf ~`'

And oops, there goes the neighborhood.

The real-world motivating case for this fix is the sed call in the recipe for
doc/index.rst in doc/Makefile. It contains a sed expression enclosed in single
quotes, containing parentheses. When run through VERBOSE with V=1, the single
quotes around the sed expression actually escape _out_ of the single-quoted
string that is intended to be the whole command line, and you get:

	/bin/sh: -c: line 1: syntax error near unexpected token `('

The fix is for VERBOSE to escape any single quotes embedded in the command line
argument when echoing it:

	VERBOSE = $(ECHO) '$(subst ','\'',$(2))'; $(2)

Note that this is still wrong, as it will not do the right thing if $(2) happens
to begin with a hyphen, but I didn't want to introduce a new "PRINTF" variable
(or do something unsavory like calling cat with a here-doc) to squash a bug that
currently has no known manifestations.

Changelog-None
2025-05-15 16:06:08 +09:30
Matt Whitlock
968bb63739 doc: properly handle ``preformatted blocks``
Lowdown requires a blank line before all preformatted blocks, or it doesn't
recognize them. `tools/md2man.sh` contained some ad-hoc efforts at fixing up
some locations where these required blank lines are absent from the output of
`tools/fromschema.py`, but it missed some. Instead of playing Whack-a-Mole, use
a blanket sed expression to ensure that a blank line precedes _every_ opening
```.

`esc_underscores(…)` in `tools/fromschema.py` did not work correctly on strings
containing an odd number of backticks, notably the ``` delimiters surrounding
preformatted text blocks. Specifically, it was dropping the last backtick since
none of the alternatives in the regex matched it. Add a new alternative that
matches a whole preformatted block as a single unit.

`output_member(…)` in `tools/fromschema.py` was passing each line of a member's
description through `esc_underscores(…)` individually, but that breaks
preformatted text blocks that are naturally multi-line and leads to mistakenly
escaping underscores inside such blocks. Rewrite the code to make use of the
`outputs(…)` utility function that joins all the provided lines together before
passing the whole text through `esc_underscores(…)`.

Drive-by fix a couple of flubbed preformatted blocks in schemas.

[ Added shellcheck suppression for md2man.sh --RR ]
Changelog-None
2025-05-15 16:06:08 +09:30
Dusty Daemon
5ef0ed3126 psbt: unused code path could leak
If `wally_psbt_extract` fails the function returns early leaking psbt, if it was `taken()`.

Throw it on tmpctx so its not leaked in this case.

Changelog-None
2025-05-15 13:16:02 +09:30
Dusty Daemon
9d773910c9 splice: Eclair Interop — reestablish corner case
Handle a specific corner case where Eclair expects us to re-send splice_locked.

Changelog-None
2025-05-15 12:47:12 +09:30
Dusty Daemon
b76c0c1d37 splice: Test fix for test crash splice
Fix a typo where the commit sig message ordering was not handled correctly for the first element.

We need to use msg_batch[0] to get the first post-sorted result instead of the original msg.

Changelog-None
2025-05-15 10:47:30 +09:30
Alex Myers
b74e156f58 pytest: search for less escaped log messages 2025-05-14 17:12:47 +09:30
Rusty Russell
bc4efc2d02 lightningd: pass all log lines to warning notifiers.
It would be wrong to omit those prior to the last, and I want to see
what test this was supposedly breaking...

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2025-05-14 17:12:47 +09:30
Rusty Russell
37d0e51701 lightningd: simplify and optimize plugin escape handling.
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2025-05-14 17:12:47 +09:30
Boris Nagaev
23997b2e1d plugin_log_handle: accommodate multi-line messages
Previously, the code utilized JSON-encoded text to pass log messages to the
log_() function, resulting in new lines being printed to the log as '\n'. This
commit addresses this issue by unescaping and splitting the log message into
lines, with each non-empty line being logged separately.

It is deemed acceptable to pass non-printable characters to log_() since they
are replaced with "?" in the logv() function, invoked by log_(). Therefore,
leaving lines JSON unescaped is permissible.

It's important to note that only the last log_() call may have call_notifier
set to true. This adjustment is crucial to prevent Python tracebacks complaining
about a broken pipe after lightningd exits.

Fix https://github.com/ElementsProject/lightning/issues/4912

For reference, the log of lightningd failing without a backend:

./lightningd/lightningd
2024-02-08T20:33:17.642Z INFO    lightningd: v23.11-257-g968d6d6-modded

Could not connect to bitcoind using bitcoin-cli. Is bitcoind running?

Make sure you have bitcoind running and that bitcoin-cli is able to connect to bitcoind.

You can verify that your Bitcoin Core installation is ready for use by running:

    $ bitcoin-cli echo 'hello world'
2024-02-08T20:33:18.227Z **BROKEN** plugin-bcli: Could not connect to bitcoind using bitcoin-cli. Is bitcoind running?
2024-02-08T20:33:18.227Z **BROKEN** plugin-bcli: Make sure you have bitcoind running and that bitcoin-cli is able to connect to bitcoind.
2024-02-08T20:33:18.227Z **BROKEN** plugin-bcli: You can verify that your Bitcoin Core installation is ready for use by running:
2024-02-08T20:33:18.227Z **BROKEN** plugin-bcli:     $ bitcoin-cli echo 'hello world'
2024-02-08T20:33:18.227Z INFO    plugin-bcli: Killing plugin: exited before we sent init
The Bitcoin backend died.

Changelog-Changed: Plugins: log messages containing \n are now split into multiple log lines, for neatness, and " is no longer turned into \".
2025-05-14 17:12:47 +09:30
Rusty Russell
833b8d11d3 pytest: fix test_bitcoind_fail_first to accept multi-line broken messages.
This will still pass once we split the lines in the next commit.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2025-05-14 17:12:47 +09:30
Alex Myers
70fa1a4b5a reckless: don't update a plugin if a specific tag was previously installed 2025-05-14 13:02:03 +09:30
Alex Myers
45d83aa01e reckless: don't return error if update is unnecessary 2025-05-14 13:02:03 +09:30
Alex Myers
666284d51f reckless: only proceed with update when appropriate 2025-05-14 13:02:03 +09:30
Alex Myers
cf767654ad reckless: return result from update 2025-05-14 13:02:03 +09:30
Alex Myers
eab84603ae reckless: provide user feedback at info level if enable fails 2025-05-14 13:02:03 +09:30
Alex Myers
741611b9a9 reckless: add update command
This updates all reckless-installed plugins with `reckless update` or
update individual plugins by passing the plugin names as arguments.

The metadata stored with the installed plugin is used to find the
plugin from the appropriate source (the same source is used as when
originally installed.)

Changelog-Added: Reckless: `reckless update` updates all reckless-installed plugins.
2025-05-14 13:02:03 +09:30
Alex Myers
f51fbc9459 reckless: refactor install
remove the duplicative search and extract the enable portion for use next.
2025-05-14 13:02:03 +09:30
Alex Myers
c526d64cc9 doc: update reckless documentation for direct install 2025-05-14 13:02:03 +09:30
Alex Myers
785fcc1af5 pytest: test reckless direct install 2025-05-14 13:02:03 +09:30
Alex Myers
1401484ba0 reckless: store absolute paths in metadata 2025-05-14 13:02:03 +09:30
Alex Myers
e9d8397c72 reckless: handle a direct source in the form of a git repo url 2025-05-14 13:02:03 +09:30
Alex Myers
3e468be1ae reckless: accept a full local path as source+name
This allows installing a local plugin directly without having
to modify reckless sources.

Changelog-changed: Reckless can be passed a local file or directory for installation.
2025-05-14 13:02:03 +09:30
Alex Myers
884ab8e616 reckless: fix installation from local directories with subpaths
This could previously copy the parent directory of a plugin
into the installed reckless directory, which was unnecessary.
2025-05-14 13:02:03 +09:30
Rusty Russell
d39220ecbc pytest: fix flake in replay tests.
channeld complains if it sees blocks going backwards, but that's
actually expected: allow those log messages:

```
2025-05-13T10:28:56.3283346Z _______________ ERROR at teardown of test_v2_replay_bookkeeping ________________
...
2025-05-13T10:28:56.3301378Z             request.node.has_errors = True
2025-05-13T10:28:56.3301833Z >           raise ValueError(str(errors))
2025-05-13T10:28:56.3302268Z E           ValueError: 
2025-05-13T10:28:56.3303425Z E           Node errors:
2025-05-13T10:28:56.3303923Z E            - lightningd-1: had BROKEN messages
2025-05-13T10:28:56.3304404Z E           Global errors:
...
2025-05-13T10:28:56.4619742Z lightningd-1 2025-05-13T10:24:38.112Z **BROKEN** 022d223620a359a47ff7f7ac447c85c46c923da53389221a0054c11c1e3ca31d59-channeld-chan#2: current blockheight 109 less than last 111
2025-05-13T10:28:56.4620188Z lightningd-2 2025-05-13T10:24:38.112Z DEBUG   0266e4598d1d3c415f572a8488830b60f7e744ed9235eb0b1ba93283b315c03518-channeld-chan#2: peer_in WIRE_SHUTDOWN
2025-05-13T10:28:56.4620600Z lightningd-1 2025-05-13T10:24:38.112Z DEBUG   022d223620a359a47ff7f7ac447c85c46c923da53389221a0054c11c1e3ca31d59-channeld-chan#2: Trying commit
2025-05-13T10:28:56.4621119Z lightningd-2 2025-05-13T10:24:38.112Z INFO    0266e4598d1d3c415f572a8488830b60f7e744ed9235eb0b1ba93283b315c03518-chan#2: State changed from CHANNELD_NORMAL to CHANNELD_SHUTTING_DOWN
2025-05-13T10:28:56.4621623Z lightningd-1 2025-05-13T10:24:38.112Z **BROKEN** 022d223620a359a47ff7f7ac447c85c46c923da53389221a0054c11c1e3ca31d59-channeld-chan#2: current blockheight 109 less than last 111
```

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2025-05-14 12:19:10 +09:30
Rusty Russell
3fc2a3b5d3 pytest: fix flake in test_pay_get_error_with_update.
We need to wait for exiting startup mode *before* closing channel, so it doesn't ignore
the disconnection of l3, otherwise we don't get a disabled update, and timeout waiting
at line 330:

    wait_for(lambda: not l1.is_channel_active(chanid2))

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2025-05-14 12:19:10 +09:30
Rusty Russell
96bfd5e009 pytest: use xpay, not pay for test_multichan_stress/
xpay should give us a better report of what's going on when this
payment fails.  Also, enable the test for v1 as well.

```
2025-05-13T03:30:44.7519949Z >       l1.rpc.pay(inv['bolt11'])
2025-05-13T03:30:44.7520207Z 
2025-05-13T03:30:44.7520362Z tests/test_connection.py:4101: 
2025-05-13T03:30:44.7520795Z _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
2025-05-13T03:30:44.7521385Z contrib/pyln-client/pyln/client/lightning.py:1174: in pay
2025-05-13T03:30:44.7521915Z     return self.call("pay", payload)
2025-05-13T03:30:44.7522424Z contrib/pyln-testing/pyln/testing/utils.py:769: in call
2025-05-13T03:30:44.7523417Z     res = LightningRpc.call(self, method, payload, cmdprefix, filter)
2025-05-13T03:30:44.7524062Z _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
2025-05-13T03:30:44.7524406Z 
2025-05-13T03:30:44.7524789Z self = <pyln.testing.utils.PrettyPrintingLightningRpc object at 0x7f3d4a216080>
2025-05-13T03:30:44.7525439Z method = 'pay'
2025-05-13T03:30:44.7527668Z payload = {'bolt11': 'lnbcrt500u1p5z9w7usp5fshywh40am006xc99743qtfhq6reurf5amzslg85h4uc9hvc4d8spp59d36m7fkzasavt46pfe97nwx9nzk3n...xpqysgqwd2nzn3gmsagdfruy9jsn0zdhy9cjy4wsj9cttlc4wftmslpm5cjtczjtn0qeqca696m6xd9vmx8vc62whty4y7wmncymletrdp9zaqqk5sf2c'}
2025-05-13T03:30:44.7530070Z cmdprefix = None, filter = None
2025-05-13T03:30:44.7530347Z 
2025-05-13T03:30:44.7530637Z     def call(self, method, payload=None, cmdprefix=None, filter=None):
2025-05-13T03:30:44.7531329Z         """Generic call API: you can set cmdprefix here, or set self.cmdprefix
2025-05-13T03:30:44.7531884Z         before the call is made.
2025-05-13T03:30:44.7532252Z     
2025-05-13T03:30:44.7532517Z         """
2025-05-13T03:30:44.7533106Z         self.logger.debug("Calling %s with payload %r", method, payload)
2025-05-13T03:30:44.7533637Z     
2025-05-13T03:30:44.7533923Z         if payload is None:
2025-05-13T03:30:44.7534292Z             payload = {}
2025-05-13T03:30:44.7534662Z         # Filter out arguments that are None
2025-05-13T03:30:44.7535120Z         if isinstance(payload, dict):
2025-05-13T03:30:44.7535634Z             payload = {k: v for k, v in payload.items() if v is not None}
2025-05-13T03:30:44.7536152Z     
2025-05-13T03:30:44.7536487Z         this_id = self.get_json_id(method, cmdprefix)
2025-05-13T03:30:44.7536944Z         self.next_id += 1
2025-05-13T03:30:44.7537274Z     
2025-05-13T03:30:44.7537635Z         # FIXME: we open a new socket for every readobj call...
2025-05-13T03:30:44.7538146Z         sock = UnixSocket(self.socket_path)
2025-05-13T03:30:44.7538550Z     
2025-05-13T03:30:44.7538809Z         buf = b''
2025-05-13T03:30:44.7539097Z     
2025-05-13T03:30:44.7539424Z         if self._notify is not None:
2025-05-13T03:30:44.7539861Z             # Opt into the notifications support
2025-05-13T03:30:44.7540297Z             self._writeobj(sock, {
2025-05-13T03:30:44.7540685Z                 "jsonrpc": "2.0",
2025-05-13T03:30:44.7541088Z                 "method": "notifications",
2025-05-13T03:30:44.7541600Z                 "id": this_id + "+notify-enable",
2025-05-13T03:30:44.7542190Z                 "params": {
2025-05-13T03:30:44.7542810Z                     "enable": True
2025-05-13T03:30:44.7543294Z                 },
2025-05-13T03:30:44.7543617Z             })
2025-05-13T03:30:44.7543853Z             # FIXME: Notification schema support?
2025-05-13T03:30:44.7544297Z             _, buf = self._readobj(sock, buf)
2025-05-13T03:30:44.7544530Z     
2025-05-13T03:30:44.7544688Z         request = {
2025-05-13T03:30:44.7544880Z             "jsonrpc": "2.0",
2025-05-13T03:30:44.7545094Z             "method": method,
2025-05-13T03:30:44.7545309Z             "params": payload,
2025-05-13T03:30:44.7545521Z             "id": this_id,
2025-05-13T03:30:44.7545714Z         }
2025-05-13T03:30:44.7545869Z     
2025-05-13T03:30:44.7546033Z         if filter is None:
2025-05-13T03:30:44.7546240Z             filter = self._filter
2025-05-13T03:30:44.7546466Z         if filter is not None:
2025-05-13T03:30:44.7546856Z             request["filter"] = filter
2025-05-13T03:30:44.7547231Z     
2025-05-13T03:30:44.7547543Z         self._writeobj(sock, request)
2025-05-13T03:30:44.7547964Z         while True:
2025-05-13T03:30:44.7548350Z             resp, buf = self._readobj(sock, buf)
2025-05-13T03:30:44.7548833Z             id = resp.get("id", None)
2025-05-13T03:30:44.7549299Z             meth = resp.get("method", None)
2025-05-13T03:30:44.7549729Z     
2025-05-13T03:30:44.7550095Z             if meth == 'message' and self._notify is not None:
2025-05-13T03:30:44.7550584Z                 n = resp['params']
2025-05-13T03:30:44.7550983Z                 self._notify(
2025-05-13T03:30:44.7551594Z                     message=n.get('message', None),
2025-05-13T03:30:44.7552133Z                     progress=n.get('progress', None),
2025-05-13T03:30:44.7552592Z                     request=request
2025-05-13T03:30:44.7553142Z                 )
2025-05-13T03:30:44.7553445Z                 continue
2025-05-13T03:30:44.7553775Z     
2025-05-13T03:30:44.7554076Z             if meth is None or id is None:
2025-05-13T03:30:44.7554483Z                 break
2025-05-13T03:30:44.7554783Z     
2025-05-13T03:30:44.7555228Z         self.logger.debug("Received response for %s call: %r", method, resp)
2025-05-13T03:30:44.7555847Z         if 'id' in resp and resp['id'] != this_id:
2025-05-13T03:30:44.7556537Z             raise ValueError("Malformed response, id is not {}: {}.".format(this_id, resp))
2025-05-13T03:30:44.7557171Z         sock.close()
2025-05-13T03:30:44.7557477Z     
2025-05-13T03:30:44.7557769Z         if not isinstance(resp, dict):
2025-05-13T03:30:44.7558413Z             raise TypeError("Malformed response, response is not a dictionary %s." % resp)
2025-05-13T03:30:44.7559049Z         elif "error" in resp:
2025-05-13T03:30:44.7559492Z >           raise RpcError(method, payload, resp['error'])
2025-05-13T03:30:44.8303393Z E           pyln.client.lightning.RpcError: RPC call failed: method: pay, payload: {'bolt11': 'lnbcrt500u1p5z9w7usp5fshywh40am006xc99743qtfhq6reurf5amzslg85h4uc9hvc4d8spp59d36m7fkzasavt46pfe97nwx9nzk3nhnkgl9qtw6t7mcswknt73sdqdd9h8vmmfvdjngxqyjw5qcqp9rzjqgkjyd3q5dv6gllh77kygly9c3kfy0d9xwyjyxsq2nq3c83u5vw4jqqqdyqqqqgqqyqqqqqpqqqqqzsqqc9qxpqysgqwd2nzn3gmsagdfruy9jsn0zdhy9cjy4wsj9cttlc4wftmslpm5cjtczjtn0qeqca696m6xd9vmx8vc62whty4y7wmncymletrdp9zaqqk5sf2c'}, error: {'code': 210, 'message': 'Ran out of routes to try after 2182 attempts: see `paystatus`', 'attempts': [{'status': 'pending', 'failreason': 'No path found', 'partid': 0, 'amount_msat': 50000000}, {'status': 'pending', 'failreason': 'No path found', 'partid': 1, 'amount_msat': 25202136, 'parent_partid': 0}, {'status': 'failed', 'failreason': 'No path found', 'partid': 6, 'amount_msat': 11590044, 'parent_partid': 1}, {'status': 'pending', 'failreason': 'No path found', 'partid': 13, 'amount_msat': 11590044, 'parent_partid': 6}, {'status': 'failed', 'failreason': 'No path found', 'partid': 20, 'amount_msat': 5340691, 'parent_partid': 13}, {'status': 'pending', 'failreason': 'No path found', 'partid': 29, 'amount_msat': 5340691, 'parent_partid': 20}, {'status': 'failed', 'failreason': 'No path found', 'partid': 38, 'amount_msat': 2860412, 'parent_partid': 29}, {'status': 'pending', 'failreason': 'No path found', 'partid': 75, 'amount_msat': 2860412, 'parent_partid': 38}, {'status': 'pending', 'failreason': 'No path found', 'partid': 165, 'amount_msat': 1301697, 'parent_partid': 75}, {'status': 'pending', 'failreason': 'No path found', 'partid': 335, 'amount_msat': 658637, 'parent_partid': 165}, {'status': 'failed', 'failreason': 'No path found', 'partid': 404, 'amount_msat': 329074, 'parent_partid': 335}, {'status': 'pending', 'failreason': 'No path found', 'partid': 509, 'amount_msat': 329074, 'parent_partid': 404}, {'status': 'failed', 'failreason': 'No path found', 'partid': 924, 'amount_msat': 151909, 'parent_partid': 509}, {'status': 'pending', 'failreason': 'No path found', 'partid': 1075, 'amount_msat': 151909, 'parent_partid': 924}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1277, 'amount_msat': 73636, 'parent_partid': 1075}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1278, 'amount_msat': 78273, 'parent_partid': 1075}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1521, 'amount_msat': 78273, 'parent_partid': 1278}, {'status': 'pending', 'failreason': 'No path found', 'partid': 925, 'amount_msat': 177165, 'parent_partid': 509}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1444, 'amount_msat': 85860, 'parent_partid': 925}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1883, 'amount_msat': 85860, 'parent_partid': 1444}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1445, 'amount_msat': 91305, 'parent_partid': 925}, {'status': 'pending', 'failreason': 'No path found', 'partid': 405, 'amount_msat': 329563, 'parent_partid': 335}, {'status': 'failed', 'failreason': 'No path found', 'partid': 510, 'amount_msat': 174463, 'parent_partid': 405}, {'status': 'pending', 'failreason': 'No path found', 'partid': 643, 'amount_msat': 174463, 'parent_partid': 510}, {'status': 'failed', 'failreason': 'No path found', 'partid': 808, 'amount_msat': 88417, 'parent_partid': 643}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1378, 'amount_msat': 88417, 'parent_partid': 808}, {'status': 'failed', 'failreason': 'No path found', 'partid': 809, 'amount_msat': 86046, 'parent_partid': 643}, {'status': 'pending', 'failreason': 'No path found', 'partid': 511, 'amount_msat': 155100, 'parent_partid': 405}, {'status': 'failed', 'failreason': 'No path found', 'partid': 644, 'amount_msat': 72741, 'parent_partid': 511}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1148, 'amount_msat': 72741, 'parent_partid': 644}, {'status': 'failed', 'failreason': 'No path found', 'partid': 645, 'amount_msat': 82359, 'parent_partid': 511}, {'status': 'failed', 'failreason': 'No path found', 'partid': 336, 'amount_msat': 643060, 'parent_partid': 165}, {'status': 'pending', 'failreason': 'No path found', 'partid': 621, 'amount_msat': 643060, 'parent_partid': 336}, {'status': 'pending', 'failreason': 'No path found', 'partid': 1021, 'amount_msat': 312772, 'parent_partid': 621}, {'status': 'pending', 'failreason': 'No path found', 'partid': 1511, 'amount_msat': 165980, 'parent_partid': 1021}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1610, 'amount_msat': 76290, 'parent_partid': 1511}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1756, 'amount_msat': 76290, 'parent_partid': 1610}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1611, 'amount_msat': 89690, 'parent_partid': 1511}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1512, 'amount_msat': 146792, 'parent_partid': 1021}, {'status': 'pending', 'failreason': 'No path found', 'partid': 1612, 'amount_msat': 146792, 'parent_partid': 1512}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1990, 'amount_msat': 67396, 'parent_partid': 1612}, {'status': 'failed', 'failreason': 'No path found', 'partid': 2137, 'amount_msat': 67396, 'parent_partid': 1990}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1991, 'amount_msat': 79396, 'parent_partid': 1612}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1022, 'amount_msat': 330288, 'parent_partid': 621}, {'status': 'pending', 'failreason': 'No path found', 'partid': 1135, 'amount_msat': 330288, 'parent_partid': 1022}, {'status': 'pending', 'failreason': 'No path found', 'partid': 1675, 'amount_msat': 171325, 'parent_partid': 1135}, {'status': 'failed', 'failreason': 'No path found', 'partid': 2007, 'amount_msat': 80351, 'parent_partid': 1675}, {'status': 'failed', 'failreason': 'No path found', 'partid': 2008, 'amount_msat': 90974, 'parent_partid': 1675}, {'status': 'failed', 'failreason': 'No path found', 'partid': 2142, 'amount_msat': 90974, 'parent_partid': 2008}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1676, 'amount_msat': 158963, 'parent_partid': 1135}, {'status': 'pending', 'failreason': 'No path found', 'partid': 1777, 'amount_msat': 158963, 'parent_partid': 1676}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1925, 'amount_msat': 78229, 'parent_partid': 1777}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1926, 'amount_msat': 80734, 'parent_partid': 1777}, {'status': 'failed', 'failreason': 'No path found', 'partid': 2117, 'amount_msat': 80734, 'parent_partid': 1926}, {'status': 'failed', 'failreason': 'No path found', 'partid': 166, 'amount_msat': 1558715, 'parent_partid': 75}, {'status': 'pending', 'failreason': 'No path found', 'partid': 210, 'amount_msat': 1558715, 'parent_partid': 166}, {'status': 'failed', 'failreason': 'No path found', 'partid': 428, 'amount_msat': 801413, 'parent_partid': 210}, {'status': 'pending', 'failreason': 'No path found', 'partid': 527, 'amount_msat': 801413, 'parent_partid': 428}, {'status': 'pending', 'failreason': 'No path found', 'partid': 657, 'amount_msat': 377626, 'parent_partid': 527}, {'status': 'pending', 'failreason': 'No path found', 'partid': 813, 'amount_msat': 193287, 'parent_partid': 657}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1028, 'amount_msat': 88356, 'parent_partid': 813}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1616, 'amount_msat': 88356, 'parent_partid': 1028}, {'status': 'pending', 'failreason': 'No path found', 'partid': 1029, 'amount_msat': 104931, 'parent_partid': 813}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1617, 'amount_msat': 53645, 'parent_partid': 1029}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1618, 'amount_msat': 51286, 'parent_partid': 1029}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1761, 'amount_msat': 51286, 'parent_partid': 1618}, {'status': 'failed', 'failreason': 'No path found', 'partid': 814, 'amount_msat': 184339, 'parent_partid': 657}, {'status': 'pending', 'failreason': 'No path found', 'partid': 1030, 'amount_msat': 184339, 'parent_partid': 814}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1619, 'amount_msat': 99183, 'parent_partid': 1030}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1620, 'amount_msat': 85156, 'parent_partid': 1030}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1762, 'amount_msat': 85156, 'parent_partid': 1620}, {'status': 'failed', 'failreason': 'No path found', 'partid': 658, 'amount_msat': 423787, 'parent_partid': 527}, {'status': 'pending', 'failreason': 'No path found', 'partid': 815, 'amount_msat': 423787, 'parent_partid': 658}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1382, 'amount_msat': 226989, 'parent_partid': 815}, {'status': 'pending', 'failreason': 'No path found', 'partid': 1561, 'amount_msat': 226989, 'parent_partid': 1382}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1968, 'amount_msat': 114759, 'parent_partid': 1561}, {'status': 'pending', 'failreason': 'No path found', 'partid': 2124, 'amount_msat': 114759, 'parent_partid': 1968}, {'status': 'failed', 'failreason': 'No path found', 'partid': 2173, 'amount_msat': 57814, 'parent_partid': 2124}, {'status': 'failed', 'failreason': 'No path found', 'partid': 2174, 'amount_msat': 56945, 'parent_partid': 2124}, {'status': 'failed', 'failreason': 'No path found', 'partid': 2179, 'amount_msat': 56945, 'parent_partid': 2174}, {'status': 'pending', 'failreason': 'No path found', 'partid': 1969, 'amount_msat': 112230, 'parent_partid': 1561}, {'status': 'failed', 'failreason': 'No path found', 'partid': 2033, 'amount_msat': 61293, 'parent_partid': 1969}, {'status': 'failed', 'failreason': 'No path found', 'partid': 2034, 'amount_msat': 50937, 'parent_partid': 1969}, {'status': 'failed', 'failreason': 'No path found', 'partid': 2102, 'amount_msat': 50937, 'parent_partid': 2034}, {'status': 'pending', 'failreason': 'No path found', 'partid': 1383, 'amount_msat': 196798, 'parent_partid': 815}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1562, 'amount_msat': 97322, 'parent_partid': 1383}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1743, 'amount_msat': 97322, 'parent_partid': 1562}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1563, 'amount_msat': 99476, 'parent_partid': 1383}, {'status': 'pending', 'failreason': 'No path found', 'partid': 429, 'amount_msat': 757302, 'parent_partid': 210}, {'status': 'failed', 'failreason': 'No path found', 'partid': 528, 'amount_msat': 359933, 'parent_partid': 429}, {'status': 'pending', 'failreason': 'No path found', 'partid': 659, 'amount_msat': 359933, 'parent_partid': 528}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1156, 'amount_msat': 174252, 'parent_partid': 659}, {'status': 'pending', 'failreason': 'No path found', 'partid': 1317, 'amount_msat': 174252, 'parent_partid': 1156}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1821, 'amount_msat': 92755, 'parent_partid': 1317}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1822, 'amount_msat': 81497, 'parent_partid': 1317}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1934, 'amount_msat': 81497, 'parent_partid': 1822}, {'status': 'pending', 'failreason': 'No path found', 'partid': 1157, 'amount_msat': 185681, 'parent_partid': 659}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1318, 'amount_msat': 98121, 'parent_partid': 1157}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1823, 'amount_msat': 98121, 'parent_partid': 1318}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1319, 'amount_msat': 87560, 'parent_partid': 1157}, {'status': 'pending', 'failreason': 'No path found', 'partid': 529, 'amount_msat': 397369, 'parent_partid': 429}, {'status': 'failed', 'failreason': 'No path found', 'partid': 660, 'amount_msat': 214870, 'parent_partid': 529}, {'status': 'pending', 'failreason': 'No path found', 'partid': 1158, 'amount_msat': 214870, 'parent_partid': 660}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1684, 'amount_msat': 116297, 'parent_partid': 1158}, {'status': 'pending', 'failreason': 'No path found', 'partid': 1784, 'amount_msat': 116297, 'parent_partid': 1684}, {'status': 'failed', 'failreason': 'No path found', 'partid': 2059, 'amount_msat': 57248, 'parent_partid': 1784}, {'status': 'failed', 'failreason': 'No path found', 'partid': 2060, 'amount_msat': 59049, 'parent_partid': 1784}, {'status': 'failed', 'failreason': 'No path found', 'partid': 2158, 'amount_msat': 59049, 'parent_partid': 2060}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1685, 'amount_msat': 98573, 'parent_partid': 1158}, {'status': 'pending', 'failreason': 'No path found', 'partid': 661, 'amount_msat': 182499, 'parent_partid': 529}, {'status': 'failed', 'failreason': 'No path found', 'partid': 816, 'amount_msat': 96426, 'parent_partid': 661}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1384, 'amount_msat': 96426, 'parent_partid': 816}, {'status': 'failed', 'failreason': 'No path found', 'partid': 817, 'amount_msat': 86073, 'parent_partid': 661}, {'status': 'pending', 'failreason': 'No path found', 'partid': 39, 'amount_msat': 2480279, 'parent_partid': 29}, {'status': 'failed', 'failreason': 'No path found', 'partid': 76, 'amount_msat': 1341671, 'parent_partid': 39}, {'status': 'pending', 'failreason': 'No path found', 'partid': 100, 'amount_msat': 1341671, 'parent_partid': 76}, {'status': 'failed', 'failreason': 'No path found', 'partid': 228, 'amount_msat': 620344, 'parent_partid': 100}, {'status': 'pending', 'failreason': 'No path found', 'partid': 450, 'amount_msat': 620344, 'parent_partid': 228}, {'status': 'failed', 'failreason': 'No path found', 'partid': 546, 'amount_msat': 328317, 'parent_partid': 450}, {'status': 'pending', 'failreason': 'No path found', 'partid': 672, 'amount_msat': 328317, 'parent_partid': 546}, {'status': 'pending', 'failreason': 'No path found', 'partid': 1163, 'amount_msat': 177416, 'parent_partid': 672}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1323, 'amount_msat': 85578, 'parent_partid': 1163}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1324, 'amount_msat': 91838, 'parent_partid': 1163}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1825, 'amount_msat': 91838, 'parent_partid': 1324}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1164, 'amount_msat': 150901, 'parent_partid': 672}, {'status': 'pending', 'failreason': 'No path found', 'partid': 1686, 'amount_msat': 150901, 'parent_partid': 1164}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1785, 'amount_msat': 74808, 'parent_partid': 1686}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1786, 'amount_msat': 76093, 'parent_partid': 1686}, {'status': 'failed', 'failreason': 'No path found', 'partid': 2061, 'amount_msat': 76093, 'parent_partid': 1786}, {'status': 'pending', 'failreason': 'No path found', 'partid': 547, 'amount_msat': 292027, 'parent_partid': 450}, {'status': 'failed', 'failreason': 'No path found', 'partid': 952, 'amount_msat': 141900, 'parent_partid': 547}, {'status': 'pending', 'failreason': 'No path found', 'partid': 1088, 'amount_msat': 141900, 'parent_partid': 952}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1287, 'amount_msat': 63901, 'parent_partid': 1088}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1288, 'amount_msat': 77999, 'parent_partid': 1088}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1806, 'amount_msat': 77999, 'parent_partid': 1288}, {'status': 'pending', 'failreason': 'No path found', 'partid': 953, 'amount_msat': 150127, 'parent_partid': 547}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1466, 'amount_msat': 81153, 'parent_partid': 953}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1897, 'amount_msat': 81153, 'parent_partid': 1466}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1467, 'amount_msat': 68974, 'parent_partid': 953}, {'status': 'pending', 'failreason': 'No path found', 'partid': 229, 'amount_msat': 721327, 'parent_partid': 100}, {'status': 'pending', 'failreason': 'No path found', 'partid': 451, 'amount_msat': 346727, 'parent_partid': 229}, {'status': 'failed', 'failreason': 'No path found', 'partid': 548, 'amount_msat': 165113, 'parent_partid': 451}, {'status': 'pending', 'failreason': 'No path found', 'partid': 673, 'amount_msat': 165113, 'parent_partid': 548}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1165, 'amount_msat': 85646, 'parent_partid': 673}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1166, 'amount_msat': 79467, 'parent_partid': 673}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1687, 'amount_msat': 79467, 'parent_partid': 1166}, {'status': 'pending', 'failreason': 'No path found', 'partid': 549, 'amount_msat': 181614, 'parent_partid': 451}, {'status': 'failed', 'failreason': 'No path found', 'partid': 954, 'amount_msat': 86180, 'parent_partid': 549}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1089, 'amount_msat': 86180, 'parent_partid': 954}, {'status': 'failed', 'failreason': 'No path found', 'partid': 955, 'amount_msat': 95434, 'parent_partid': 549}, {'status': 'failed', 'failreason': 'No path found', 'partid': 452, 'amount_msat': 374600, 'parent_partid': 229}, {'status': 'pending', 'failreason': 'No path found', 'partid': 783, 'amount_msat': 374600, 'parent_partid': 452}, {'status': 'pending', 'failreason': 'No path found', 'partid': 889, 'amount_msat': 198755, 'parent_partid': 783}, {'status': 'pending', 'failreason': 'No path found', 'partid': 1423, 'amount_msat': 108131, 'parent_partid': 889}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1864, 'amount_msat': 57820, 'parent_partid': 1423}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1940, 'amount_msat': 57820, 'parent_partid': 1864}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1865, 'amount_msat': 50311, 'parent_partid': 1423}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1424, 'amount_msat': 90624, 'parent_partid': 889}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1576, 'amount_msat': 90624, 'parent_partid': 1424}, {'status': 'failed', 'failreason': 'No path found', 'partid': 890, 'amount_msat': 175845, 'parent_partid': 783}, {'status': 'pending', 'failreason': 'No path found', 'partid': 1055, 'amount_msat': 175845, 'parent_partid': 890}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1266, 'amount_msat': 93465, 'parent_partid': 1055}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1519, 'amount_msat': 93465, 'parent_partid': 1266}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1267, 'amount_msat': 82380, 'parent_partid': 1055}, {'status': 'pending', 'failreason': 'No path found', 'partid': 77, 'amount_msat': 1138608, 'parent_partid': 39}, {'status': 'pending', 'failreason': 'No path found', 'partid': 167, 'amount_msat': 563284, 'parent_partid': 77}, {'status': 'pending', 'failreason': 'No path found', 'partid': 211, 'amount_msat': 286967, 'parent_partid': 167}, {'status': 'failed', 'failreason': 'No path found', 'partid': 430, 'amount_msat': 132425, 'parent_partid': 211}, {'status': 'pending', 'failreason': 'No path found', 'partid': 769, 'amount_msat': 132425, 'parent_partid': 430}, {'status': 'failed', 'failreason': 'No path found', 'partid': 884, 'amount_msat': 63488, 'parent_partid': 769}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1422, 'amount_msat': 63488, 'parent_partid': 884}, {'status': 'failed', 'failreason': 'No path found', 'partid': 885, 'amount_msat': 68937, 'parent_partid': 769}, {'status': 'pending', 'failreason': 'No path found', 'partid': 431, 'amount_msat': 154542, 'parent_partid': 211}, {'status': 'failed', 'failreason': 'No path found', 'partid': 770, 'amount_msat': 81294, 'parent_partid': 431}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1230, 'amount_msat': 81294, 'parent_partid': 770}, {'status': 'failed', 'failreason': 'No path found', 'partid': 771, 'amount_msat': 73248, 'parent_partid': 431}, {'status': 'failed', 'failreason': 'No path found', 'partid': 212, 'amount_msat': 276317, 'parent_partid': 167}, {'status': 'pending', 'failreason': 'No path found', 'partid': 290, 'amount_msat': 276317, 'parent_partid': 212}, {'status': 'pending', 'failreason': 'No path found', 'partid': 367, 'amount_msat': 134849, 'parent_partid': 290}, {'status': 'failed', 'failreason': 'No path found', 'partid': 725, 'amount_msat': 68680, 'parent_partid': 367}, {'status': 'failed', 'failreason': 'No path found', 'partid': 726, 'amount_msat': 66169, 'parent_partid': 367}, {'status': 'failed', 'failreason': 'No path found', 'partid': 858, 'amount_msat': 66169, 'parent_partid': 726}, {'status': 'failed', 'failreason': 'No path found', 'partid': 368, 'amount_msat': 141468, 'parent_partid': 290}, {'status': 'pending', 'failreason': 'No path found', 'partid': 481, 'amount_msat': 141468, 'parent_partid': 368}, {'status': 'failed', 'failreason': 'No path found', 'partid': 901, 'amount_msat': 71681, 'parent_partid': 481}, {'status': 'failed', 'failreason': 'No path found', 'partid': 902, 'amount_msat': 69787, 'parent_partid': 481}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1060, 'amount_msat': 69787, 'parent_partid': 902}, {'status': 'failed', 'failreason': 'No path found', 'partid': 168, 'amount_msat': 575324, 'parent_partid': 77}, {'status': 'pending', 'failreason': 'No path found', 'partid': 337, 'amount_msat': 575324, 'parent_partid': 168}, {'status': 'failed', 'failreason': 'No path found', 'partid': 622, 'amount_msat': 315685, 'parent_partid': 337}, {'status': 'pending', 'failreason': 'No path found', 'partid': 708, 'amount_msat': 315685, 'parent_partid': 622}, {'status': 'pending', 'failreason': 'No path found', 'partid': 1183, 'amount_msat': 149551, 'parent_partid': 708}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1697, 'amount_msat': 79509, 'parent_partid': 1183}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1698, 'amount_msat': 70042, 'parent_partid': 1183}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1791, 'amount_msat': 70042, 'parent_partid': 1698}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1184, 'amount_msat': 166134, 'parent_partid': 708}, {'status': 'pending', 'failreason': 'No path found', 'partid': 1699, 'amount_msat': 166134, 'parent_partid': 1184}, {'status': 'failed', 'failreason': 'No path found', 'partid': 2012, 'amount_msat': 87333, 'parent_partid': 1699}, {'status': 'failed', 'failreason': 'No path found', 'partid': 2144, 'amount_msat': 87333, 'parent_partid': 2012}, {'status': 'failed', 'failreason': 'No path found', 'partid': 2013, 'amount_msat': 78801, 'parent_partid': 1699}, {'status': 'pending', 'failreason': 'No path found', 'partid': 623, 'amount_msat': 259639, 'parent_partid': 337}, {'status': 'pending', 'failreason': 'No path found', 'partid': 709, 'amount_msat': 130083, 'parent_partid': 623}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1185, 'amount_msat': 62022, 'parent_partid': 709}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1186, 'amount_msat': 68061, 'parent_partid': 709}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1330, 'amount_msat': 68061, 'parent_partid': 1186}, {'status': 'failed', 'failreason': 'No path found', 'partid': 710, 'amount_msat': 129556, 'parent_partid': 623}, {'status': 'pending', 'failreason': 'No path found', 'partid': 853, 'amount_msat': 129556, 'parent_partid': 710}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1040, 'amount_msat': 64789, 'parent_partid': 853}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1262, 'amount_msat': 64789, 'parent_partid': 1040}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1041, 'amount_msat': 64767, 'parent_partid': 853}, {'status': 'pending', 'failreason': 'No path found', 'partid': 21, 'amount_msat': 6249353, 'parent_partid': 13}, {'status': 'pending', 'failreason': 'No path found', 'partid': 43, 'amount_msat': 3278901, 'parent_partid': 21}, {'status': 'failed', 'failreason': 'No path found', 'partid': 82, 'amount_msat': 1557184, 'parent_partid': 43}, {'status': 'pending', 'failreason': 'No path found', 'partid': 170, 'amount_msat': 1557184, 'parent_partid': 82}, {'status': 'failed', 'failreason': 'No path found', 'partid': 340, 'amount_msat': 796327, 'parent_partid': 170}, {'status': 'pending', 'failreason': 'No path found', 'partid': 408, 'amount_msat': 796327, 'parent_partid': 340}, {'status': 'failed', 'failreason': 'No path found', 'partid': 514, 'amount_msat': 377079, 'parent_partid': 408}, {'status': 'pending', 'failreason': 'No path found', 'partid': 646, 'amount_msat': 377079, 'parent_partid': 514}, {'status': 'pending', 'failreason': 'No path found', 'partid': 1149, 'amount_msat': 190647, 'parent_partid': 646}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1312, 'amount_msat': 88150, 'parent_partid': 1149}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1534, 'amount_msat': 88150, 'parent_partid': 1312}, {'status': 'pending', 'failreason': 'No path found', 'partid': 1313, 'amount_msat': 102497, 'parent_partid': 1149}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1818, 'amount_msat': 53153, 'parent_partid': 1313}, {'status': 'failed', 'failreason': 'No path found', 'partid': 2066, 'amount_msat': 53153, 'parent_partid': 1818}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1819, 'amount_msat': 49344, 'parent_partid': 1313}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1150, 'amount_msat': 186432, 'parent_partid': 646}, {'status': 'pending', 'failreason': 'No path found', 'partid': 1314, 'amount_msat': 186432, 'parent_partid': 1150}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1535, 'amount_msat': 90325, 'parent_partid': 1314}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1536, 'amount_msat': 96107, 'parent_partid': 1314}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1955, 'amount_msat': 96107, 'parent_partid': 1536}, {'status': 'pending', 'failreason': 'No path found', 'partid': 515, 'amount_msat': 419248, 'parent_partid': 408}, {'status': 'pending', 'failreason': 'No path found', 'partid': 647, 'amount_msat': 227560, 'parent_partid': 515}, {'status': 'pending', 'failreason': 'No path found', 'partid': 1151, 'amount_msat': 115214, 'parent_partid': 647}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1315, 'amount_msat': 59991, 'parent_partid': 1151}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1316, 'amount_msat': 55223, 'parent_partid': 1151}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1820, 'amount_msat': 55223, 'parent_partid': 1316}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1152, 'amount_msat': 112346, 'parent_partid': 647}, {'status': 'pending', 'failreason': 'No path found', 'partid': 1681, 'amount_msat': 112346, 'parent_partid': 1152}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1781, 'amount_msat': 58702, 'parent_partid': 1681}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1782, 'amount_msat': 53644, 'parent_partid': 1681}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1930, 'amount_msat': 53644, 'parent_partid': 1782}, {'status': 'failed', 'failreason': 'No path found', 'partid': 648, 'amount_msat': 191688, 'parent_partid': 515}, {'status': 'pending', 'failreason': 'No path found', 'partid': 810, 'amount_msat': 191688, 'parent_partid': 648}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1379, 'amount_msat': 91459, 'parent_partid': 810}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1380, 'amount_msat': 100229, 'parent_partid': 810}, {'status': 'pending', 'failreason': 'No path found', 'partid': 1850, 'amount_msat': 100229, 'parent_partid': 1380}, {'status': 'failed', 'failreason': 'No path found', 'partid': 2076, 'amount_msat': 47738, 'parent_partid': 1850}, {'status': 'failed', 'failreason': 'No path found', 'partid': 2163, 'amount_msat': 47738, 'parent_partid': 2076}, {'status': 'failed', 'failreason': 'No path found', 'partid': 2077, 'amount_msat': 52491, 'parent_partid': 1850}, {'status': 'pending', 'failreason': 'No path found', 'partid': 341, 'amount_msat': 760857, 'parent_partid': 170}, {'status': 'pending', 'failreason': 'No path found', 'partid': 625, 'amount_msat': 408211, 'parent_partid': 341}, {'status': 'pending', 'failreason': 'No path found', 'partid': 1023, 'amount_msat': 204958, 'parent_partid': 625}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1136, 'amount_msat': 109033, 'parent_partid': 1023}, {'status': 'pending', 'failreason': 'No path found', 'partid': 1308, 'amount_msat': 109033, 'parent_partid': 1136}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1815, 'amount_msat': 57939, 'parent_partid': 1308}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1816, 'amount_msat': 51094, 'parent_partid': 1308}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1933, 'amount_msat': 51094, 'parent_partid': 1816}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1137, 'amount_msat': 95925, 'parent_partid': 1023}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1024, 'amount_msat': 203253, 'parent_partid': 625}, {'status': 'pending', 'failreason': 'No path found', 'partid': 1513, 'amount_msat': 203253, 'parent_partid': 1024}, {'status': 'pending', 'failreason': 'No path found', 'partid': 1613, 'amount_msat': 109349, 'parent_partid': 1513}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1757, 'amount_msat': 50515, 'parent_partid': 1613}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1758, 'amount_msat': 58834, 'parent_partid': 1613}, {'status': 'failed', 'failreason': 'No path found', 'partid': 2056, 'amount_msat': 58834, 'parent_partid': 1758}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1614, 'amount_msat': 93904, 'parent_partid': 1513}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1992, 'amount_msat': 93904, 'parent_partid': 1614}, {'status': 'failed', 'failreason': 'No path found', 'partid': 626, 'amount_msat': 352646, 'parent_partid': 341}, {'status': 'pending', 'failreason': 'No path found', 'partid': 1025, 'amount_msat': 352646, 'parent_partid': 626}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1514, 'amount_msat': 164352, 'parent_partid': 1025}, {'status': 'pending', 'failreason': 'No path found', 'partid': 1615, 'amount_msat': 164352, 'parent_partid': 1514}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1759, 'amount_msat': 89392, 'parent_partid': 1615}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1760, 'amount_msat': 74960, 'parent_partid': 1615}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1922, 'amount_msat': 74960, 'parent_partid': 1760}, {'status': 'pending', 'failreason': 'No path found', 'partid': 1515, 'amount_msat': 188294, 'parent_partid': 1025}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1915, 'amount_msat': 92358, 'parent_partid': 1515}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1916, 'amount_msat': 95936, 'parent_partid': 1515}, {'status': 'failed', 'failreason': 'No path found', 'partid': 2100, 'amount_msat': 95936, 'parent_partid': 1916}, {'status': 'pending', 'failreason': 'No path found', 'partid': 83, 'amount_msat': 1721717, 'parent_partid': 43}, {'status': 'failed', 'failreason': 'No path found', 'partid': 106, 'amount_msat': 925248, 'parent_partid': 83}, {'status': 'pending', 'failreason': 'No path found', 'partid': 233, 'amount_msat': 925248, 'parent_partid': 106}, {'status': 'pending', 'failreason': 'No path found', 'partid': 297, 'amount_msat': 458761, 'parent_partid': 233}, {'status': 'failed', 'failreason': 'No path found', 'partid': 592, 'amount_msat': 244389, 'parent_partid': 297}, {'status': 'pending', 'failreason': 'No path found', 'partid': 690, 'amount_msat': 244389, 'parent_partid': 592}, {'status': 'failed', 'failreason': 'No path found', 'partid': 838, 'amount_msat': 129641, 'parent_partid': 690}, {'status': 'pending', 'failreason': 'No path found', 'partid': 1400, 'amount_msat': 129641, 'parent_partid': 838}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1857, 'amount_msat': 68380, 'parent_partid': 1400}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1858, 'amount_msat': 61261, 'parent_partid': 1400}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1939, 'amount_msat': 61261, 'parent_partid': 1858}, {'status': 'pending', 'failreason': 'No path found', 'partid': 839, 'amount_msat': 114748, 'parent_partid': 690}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1401, 'amount_msat': 54890, 'parent_partid': 839}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1402, 'amount_msat': 59858, 'parent_partid': 839}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1859, 'amount_msat': 59858, 'parent_partid': 1402}, {'status': 'pending', 'failreason': 'No path found', 'partid': 593, 'amount_msat': 214372, 'parent_partid': 297}, {'status': 'failed', 'failreason': 'No path found', 'partid': 992, 'amount_msat': 111862, 'parent_partid': 593}, {'status': 'pending', 'failreason': 'No path found', 'partid': 1120, 'amount_msat': 111862, 'parent_partid': 992}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1295, 'amount_msat': 61052, 'parent_partid': 1120}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1296, 'amount_msat': 50810, 'parent_partid': 1120}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1527, 'amount_msat': 50810, 'parent_partid': 1296}, {'status': 'pending', 'failreason': 'No path found', 'partid': 993, 'amount_msat': 102510, 'parent_partid': 593}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1488, 'amount_msat': 50408, 'parent_partid': 993}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1905, 'amount_msat': 50408, 'parent_partid': 1488}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1489, 'amount_msat': 52102, 'parent_partid': 993}, {'status': 'failed', 'failreason': 'No path found', 'partid': 298, 'amount_msat': 466487, 'parent_partid': 233}, {'status': 'pending', 'failreason': 'No path found', 'partid': 594, 'amount_msat': 466487, 'parent_partid': 298}, {'status': 'failed', 'failreason': 'No path found', 'partid': 994, 'amount_msat': 215749, 'parent_partid': 594}, {'status': 'pending', 'failreason': 'No path found', 'partid': 1490, 'amount_msat': 215749, 'parent_partid': 994}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1594, 'amount_msat': 104373, 'parent_partid': 1490}, {'status': 'pending', 'failreason': 'No path found', 'partid': 1986, 'amount_msat': 104373, 'parent_partid': 1594}, {'status': 'failed', 'failreason': 'No path found', 'partid': 2131, 'amount_msat': 55654, 'parent_partid': 1986}, {'status': 'failed', 'failreason': 'No path found', 'partid': 2132, 'amount_msat': 48719, 'parent_partid': 1986}, {'status': 'failed', 'failreason': 'No path found', 'partid': 2149, 'amount_msat': 48719, 'parent_partid': 2132}, {'status': 'pending', 'failreason': 'No path found', 'partid': 1595, 'amount_msat': 111376, 'parent_partid': 1490}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1748, 'amount_msat': 54109, 'parent_partid': 1595}, {'status': 'failed', 'failreason': 'No path found', 'partid': 2052, 'amount_msat': 54109, 'parent_partid': 1748}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1749, 'amount_msat': 57267, 'parent_partid': 1595}, {'status': 'pending', 'failreason': 'No path found', 'partid': 995, 'amount_msat': 250738, 'parent_partid': 594}, {'status': 'pending', 'failreason': 'No path found', 'partid': 1121, 'amount_msat': 126195, 'parent_partid': 995}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1297, 'amount_msat': 62444, 'parent_partid': 1121}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1298, 'amount_msat': 63751, 'parent_partid': 1121}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1811, 'amount_msat': 63751, 'parent_partid': 1298}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1122, 'amount_msat': 124543, 'parent_partid': 995}, {'status': 'pending', 'failreason': 'No path found', 'partid': 1299, 'amount_msat': 124543, 'parent_partid': 1122}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1528, 'amount_msat': 60961, 'parent_partid': 1299}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1731, 'amount_msat': 60961, 'parent_partid': 1528}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1529, 'amount_msat': 63582, 'parent_partid': 1299}, {'status': 'pending', 'failreason': 'No path found', 'partid': 107, 'amount_msat': 796469, 'parent_partid': 83}, {'status': 'pending', 'failreason': 'No path found', 'partid': 141, 'amount_msat': 360383, 'parent_partid': 107}, {'status': 'pending', 'failreason': 'No path found', 'partid': 185, 'amount_msat': 164534, 'parent_partid': 141}, {'status': 'failed', 'failreason': 'No path found', 'partid': 262, 'amount_msat': 80672, 'parent_partid': 185}, {'status': 'failed', 'failreason': 'No path found', 'partid': 566, 'amount_msat': 80672, 'parent_partid': 262}, {'status': 'failed', 'failreason': 'No path found', 'partid': 263, 'amount_msat': 83862, 'parent_partid': 185}, {'status': 'failed', 'failreason': 'No path found', 'partid': 186, 'amount_msat': 195849, 'parent_partid': 141}, {'status': 'pending', 'failreason': 'No path found', 'partid': 264, 'amount_msat': 195849, 'parent_partid': 186}, {'status': 'failed', 'failreason': 'No path found', 'partid': 348, 'amount_msat': 90197, 'parent_partid': 264}, {'status': 'failed', 'failreason': 'No path found', 'partid': 473, 'amount_msat': 90197, 'parent_partid': 348}, {'status': 'pending', 'failreason': 'No path found', 'partid': 349, 'amount_msat': 105652, 'parent_partid': 264}, {'status': 'failed', 'failreason': 'No path found', 'partid': 713, 'amount_msat': 57623, 'parent_partid': 349}, {'status': 'failed', 'failreason': 'No path found', 'partid': 714, 'amount_msat': 48029, 'parent_partid': 349}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1188, 'amount_msat': 48029, 'parent_partid': 714}, {'status': 'failed', 'failreason': 'No path found', 'partid': 142, 'amount_msat': 436086, 'parent_partid': 107}, {'status': 'pending', 'failreason': 'No path found', 'partid': 320, 'amount_msat': 436086, 'parent_partid': 142}, {'status': 'pending', 'failreason': 'No path found', 'partid': 611, 'amount_msat': 203712, 'parent_partid': 320}, {'status': 'failed', 'failreason': 'No path found', 'partid': 698, 'amount_msat': 97970, 'parent_partid': 611}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1177, 'amount_msat': 97970, 'parent_partid': 698}, {'status': 'pending', 'failreason': 'No path found', 'partid': 699, 'amount_msat': 105742, 'parent_partid': 611}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1178, 'amount_msat': 49532, 'parent_partid': 699}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1329, 'amount_msat': 49532, 'parent_partid': 1178}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1179, 'amount_msat': 56210, 'parent_partid': 699}, {'status': 'failed', 'failreason': 'No path found', 'partid': 612, 'amount_msat': 232374, 'parent_partid': 320}, {'status': 'pending', 'failreason': 'No path found', 'partid': 700, 'amount_msat': 232374, 'parent_partid': 612}, {'status': 'pending', 'failreason': 'No path found', 'partid': 847, 'amount_msat': 113893, 'parent_partid': 700}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1407, 'amount_msat': 55534, 'parent_partid': 847}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1408, 'amount_msat': 58359, 'parent_partid': 847}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1861, 'amount_msat': 58359, 'parent_partid': 1408}, {'status': 'failed', 'failreason': 'No path found', 'partid': 848, 'amount_msat': 118481, 'parent_partid': 700}, {'status': 'pending', 'failreason': 'No path found', 'partid': 1038, 'amount_msat': 118481, 'parent_partid': 848}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1260, 'amount_msat': 57632, 'parent_partid': 1038}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1516, 'amount_msat': 57632, 'parent_partid': 1260}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1261, 'amount_msat': 60849, 'parent_partid': 1038}, {'status': 'failed', 'failreason': 'No path found', 'partid': 44, 'amount_msat': 2970452, 'parent_partid': 21}, {'status': 'pending', 'failreason': 'No path found', 'partid': 84, 'amount_msat': 2970452, 'parent_partid': 44}, {'status': 'failed', 'failreason': 'No path found', 'partid': 108, 'amount_msat': 1422639, 'parent_partid': 84}, {'status': 'pending', 'failreason': 'No path found', 'partid': 143, 'amount_msat': 1422639, 'parent_partid': 108}, {'status': 'pending', 'failreason': 'No path found', 'partid': 187, 'amount_msat': 758781, 'parent_partid': 143}, {'status': 'pending', 'failreason': 'No path found', 'partid': 265, 'amount_msat': 347693, 'parent_partid': 187}, {'status': 'failed', 'failreason': 'No path found', 'partid': 350, 'amount_msat': 185104, 'parent_partid': 265}, {'status': 'pending', 'failreason': 'No path found', 'partid': 474, 'amount_msat': 185104, 'parent_partid': 350}, {'status': 'failed', 'failreason': 'No path found', 'partid': 897, 'amount_msat': 97549, 'parent_partid': 474}, {'status': 'failed', 'failreason': 'No path found', 'partid': 898, 'amount_msat': 87555, 'parent_partid': 474}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1429, 'amount_msat': 87555, 'parent_partid': 898}, {'status': 'pending', 'failreason': 'No path found', 'partid': 351, 'amount_msat': 162589, 'parent_partid': 265}, {'status': 'failed', 'failreason': 'No path found', 'partid': 715, 'amount_msat': 73245, 'parent_partid': 351}, {'status': 'failed', 'failreason': 'No path found', 'partid': 716, 'amount_msat': 89344, 'parent_partid': 351}, {'status': 'failed', 'failreason': 'No path found', 'partid': 856, 'amount_msat': 89344, 'parent_partid': 716}, {'status': 'failed', 'failreason': 'No path found', 'partid': 266, 'amount_msat': 411088, 'parent_partid': 187}, {'status': 'pending', 'failreason': 'No path found', 'partid': 567, 'amount_msat': 411088, 'parent_partid': 266}, {'status': 'failed', 'failreason': 'No path found', 'partid': 974, 'amount_msat': 213374, 'parent_partid': 567}, {'status': 'pending', 'failreason': 'No path found', 'partid': 1103, 'amount_msat': 213374, 'parent_partid': 974}, {'status': 'pending', 'failreason': 'No path found', 'partid': 1289, 'amount_msat': 114303, 'parent_partid': 1103}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1807, 'amount_msat': 55066, 'parent_partid': 1289}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1808, 'amount_msat': 59237, 'parent_partid': 1289}, {'status': 'failed', 'failreason': 'No path found', 'partid': 2065, 'amount_msat': 59237, 'parent_partid': 1808}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1290, 'amount_msat': 99071, 'parent_partid': 1103}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1809, 'amount_msat': 99071, 'parent_partid': 1290}, {'status': 'pending', 'failreason': 'No path found', 'partid': 975, 'amount_msat': 197714, 'parent_partid': 567}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1104, 'amount_msat': 91184, 'parent_partid': 975}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1655, 'amount_msat': 91184, 'parent_partid': 1104}, {'status': 'pending', 'failreason': 'No path found', 'partid': 1105, 'amount_msat': 106530, 'parent_partid': 975}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1656, 'amount_msat': 55499, 'parent_partid': 1105}, {'status': 'failed', 'failreason': 'No path found', 'partid': 2000, 'amount_msat': 55499, 'parent_partid': 1656}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1657, 'amount_msat': 51031, 'parent_partid': 1105}, {'status': 'failed', 'failreason': 'No path found', 'partid': 188, 'amount_msat': 663858, 'parent_partid': 143}, {'status': 'pending', 'failreason': 'No path found', 'partid': 417, 'amount_msat': 663858, 'parent_partid': 188}, {'status': 'failed', 'failreason': 'No path found', 'partid': 522, 'amount_msat': 308638, 'parent_partid': 417}, {'status': 'pending', 'failreason': 'No path found', 'partid': 936, 'amount_msat': 308638, 'parent_partid': 522}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1454, 'amount_msat': 156915, 'parent_partid': 936}, {'status': 'pending', 'failreason': 'No path found', 'partid': 1890, 'amount_msat': 156915, 'parent_partid': 1454}, {'status': 'failed', 'failreason': 'No path found', 'partid': 2090, 'amount_msat': 75009, 'parent_partid': 1890}, {'status': 'failed', 'failreason': 'No path found', 'partid': 2164, 'amount_msat': 75009, 'parent_partid': 2090}, {'status': 'failed', 'failreason': 'No path found', 'partid': 2091, 'amount_msat': 81906, 'parent_partid': 1890}, {'status': 'pending', 'failreason': 'No path found', 'partid': 1455, 'amount_msat': 151723, 'parent_partid': 936}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1891, 'amount_msat': 73261, 'parent_partid': 1455}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1892, 'amount_msat': 78462, 'parent_partid': 1455}, {'status': 'failed', 'failreason': 'No path found', 'partid': 2092, 'amount_msat': 78462, 'parent_partid': 1892}, {'status': 'pending', 'failreason': 'No path found', 'partid': 523, 'amount_msat': 355220, 'parent_partid': 417}, {'status': 'failed', 'failreason': 'No path found', 'partid': 652, 'amount_msat': 163945, 'parent_partid': 523}, {'status': 'pending', 'failreason': 'No path found', 'partid': 1154, 'amount_msat': 163945, 'parent_partid': 652}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1682, 'amount_msat': 88265, 'parent_partid': 1154}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1783, 'amount_msat': 88265, 'parent_partid': 1682}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1683, 'amount_msat': 75680, 'parent_partid': 1154}, {'status': 'pending', 'failreason': 'No path found', 'partid': 653, 'amount_msat': 191275, 'parent_partid': 523}, {'status': 'failed', 'failreason': 'No path found', 'partid': 811, 'amount_msat': 92684, 'parent_partid': 653}, {'status': 'failed', 'failreason': 'No path found', 'partid': 812, 'amount_msat': 98591, 'parent_partid': 653}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1381, 'amount_msat': 98591, 'parent_partid': 812}, {'status': 'pending', 'failreason': 'No path found', 'partid': 109, 'amount_msat': 1547813, 'parent_partid': 84}, {'status': 'failed', 'failreason': 'No path found', 'partid': 144, 'amount_msat': 791897, 'parent_partid': 109}, {'status': 'pending', 'failreason': 'No path found', 'partid': 189, 'amount_msat': 791897, 'parent_partid': 144}, {'status': 'pending', 'failreason': 'No path found', 'partid': 267, 'amount_msat': 361080, 'parent_partid': 189}, {'status': 'failed', 'failreason': 'No path found', 'partid': 568, 'amount_msat': 183859, 'parent_partid': 267}, {'status': 'pending', 'failreason': 'No path found', 'partid': 976, 'amount_msat': 183859, 'parent_partid': 568}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1479, 'amount_msat': 83082, 'parent_partid': 976}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1480, 'amount_msat': 100777, 'parent_partid': 976}, {'status': 'pending', 'failreason': 'No path found', 'partid': 1590, 'amount_msat': 100777, 'parent_partid': 1480}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1979, 'amount_msat': 53201, 'parent_partid': 1590}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1980, 'amount_msat': 47576, 'parent_partid': 1590}, {'status': 'failed', 'failreason': 'No path found', 'partid': 2129, 'amount_msat': 47576, 'parent_partid': 1980}, {'status': 'pending', 'failreason': 'No path found', 'partid': 569, 'amount_msat': 177221, 'parent_partid': 267}, {'status': 'failed', 'failreason': 'No path found', 'partid': 677, 'amount_msat': 85241, 'parent_partid': 569}, {'status': 'failed', 'failreason': 'No path found', 'partid': 678, 'amount_msat': 91980, 'parent_partid': 569}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1171, 'amount_msat': 91980, 'parent_partid': 678}, {'status': 'failed', 'failreason': 'No path found', 'partid': 268, 'amount_msat': 430817, 'parent_partid': 189}, {'status': 'pending', 'failreason': 'No path found', 'partid': 570, 'amount_msat': 430817, 'parent_partid': 268}, {'status': 'pending', 'failreason': 'No path found', 'partid': 977, 'amount_msat': 196434, 'parent_partid': 570}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1106, 'amount_msat': 95338, 'parent_partid': 977}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1658, 'amount_msat': 95338, 'parent_partid': 1106}, {'status': 'pending', 'failreason': 'No path found', 'partid': 1107, 'amount_msat': 101096, 'parent_partid': 977}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1291, 'amount_msat': 52630, 'parent_partid': 1107}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1292, 'amount_msat': 48466, 'parent_partid': 1107}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1810, 'amount_msat': 48466, 'parent_partid': 1292}, {'status': 'failed', 'failreason': 'No path found', 'partid': 978, 'amount_msat': 234383, 'parent_partid': 570}, {'status': 'pending', 'failreason': 'No path found', 'partid': 1108, 'amount_msat': 234383, 'parent_partid': 978}, {'status': 'pending', 'failreason': 'No path found', 'partid': 1659, 'amount_msat': 116012, 'parent_partid': 1108}, {'status': 'failed', 'failreason': 'No path found', 'partid': 2001, 'amount_msat': 58861, 'parent_partid': 1659}, {'status': 'failed', 'failreason': 'No path found', 'partid': 2002, 'amount_msat': 57151, 'parent_partid': 1659}, {'status': 'failed', 'failreason': 'No path found', 'partid': 2139, 'amount_msat': 57151, 'parent_partid': 2002}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1660, 'amount_msat': 118371, 'parent_partid': 1108}, {'status': 'pending', 'failreason': 'No path found', 'partid': 2003, 'amount_msat': 118371, 'parent_partid': 1660}, {'status': 'failed', 'failreason': 'No path found', 'partid': 2140, 'amount_msat': 58092, 'parent_partid': 2003}, {'status': 'failed', 'failreason': 'No path found', 'partid': 2177, 'amount_msat': 58092, 'parent_partid': 2140}, {'status': 'failed', 'failreason': 'No path found', 'partid': 2141, 'amount_msat': 60279, 'parent_partid': 2003}, {'status': 'pending', 'failreason': 'No path found', 'partid': 145, 'amount_msat': 755916, 'parent_partid': 109}, {'status': 'failed', 'failreason': 'No path found', 'partid': 190, 'amount_msat': 411361, 'parent_partid': 145}, {'status': 'pending', 'failreason': 'No path found', 'partid': 269, 'amount_msat': 411361, 'parent_partid': 190}, {'status': 'failed', 'failreason': 'No path found', 'partid': 352, 'amount_msat': 208549, 'parent_partid': 269}, {'status': 'pending', 'failreason': 'No path found', 'partid': 717, 'amount_msat': 208549, 'parent_partid': 352}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1189, 'amount_msat': 99996, 'parent_partid': 717}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1190, 'amount_msat': 108553, 'parent_partid': 717}, {'status': 'pending', 'failreason': 'No path found', 'partid': 1333, 'amount_msat': 108553, 'parent_partid': 1190}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1828, 'amount_msat': 55505, 'parent_partid': 1333}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1935, 'amount_msat': 55505, 'parent_partid': 1828}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1829, 'amount_msat': 53048, 'parent_partid': 1333}, {'status': 'pending', 'failreason': 'No path found', 'partid': 353, 'amount_msat': 202812, 'parent_partid': 269}, {'status': 'failed', 'failreason': 'No path found', 'partid': 718, 'amount_msat': 98191, 'parent_partid': 353}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1191, 'amount_msat': 98191, 'parent_partid': 718}, {'status': 'pending', 'failreason': 'No path found', 'partid': 719, 'amount_msat': 104621, 'parent_partid': 353}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1192, 'amount_msat': 49156, 'parent_partid': 719}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1700, 'amount_msat': 49156, 'parent_partid': 1192}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1193, 'amount_msat': 55465, 'parent_partid': 719}, {'status': 'pending', 'failreason': 'No path found', 'partid': 191, 'amount_msat': 344555, 'parent_partid': 145}, {'status': 'failed', 'failreason': 'No path found', 'partid': 418, 'amount_msat': 177431, 'parent_partid': 191}, {'status': 'pending', 'failreason': 'No path found', 'partid': 524, 'amount_msat': 177431, 'parent_partid': 418}, {'status': 'failed', 'failreason': 'No path found', 'partid': 654, 'amount_msat': 94731, 'parent_partid': 524}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1155, 'amount_msat': 94731, 'parent_partid': 654}, {'status': 'failed', 'failreason': 'No path found', 'partid': 655, 'amount_msat': 82700, 'parent_partid': 524}, {'status': 'pending', 'failreason': 'No path found', 'partid': 419, 'amount_msat': 167124, 'parent_partid': 191}, {'status': 'failed', 'failreason': 'No path found', 'partid': 525, 'amount_msat': 89227, 'parent_partid': 419}, {'status': 'failed', 'failreason': 'No path found', 'partid': 526, 'amount_msat': 77897, 'parent_partid': 419}, {'status': 'failed', 'failreason': 'No path found', 'partid': 656, 'amount_msat': 77897, 'parent_partid': 526}, {'status': 'pending', 'failreason': 'No path found', 'partid': 7, 'amount_msat': 13612092, 'parent_partid': 1}, {'status': 'failed', 'failreason': 'No path found', 'partid': 14, 'amount_msat': 6823774, 'parent_partid': 7}, {'status': 'pending', 'failreason': 'No path found', 'partid': 22, 'amount_msat': 6823774, 'parent_partid': 14}, {'status': 'failed', 'failreason': 'No path found', 'partid': 30, 'amount_msat': 3660597, 'parent_partid': 22}, {'status': 'pending', 'failreason': 'No path found', 'partid': 58, 'amount_msat': 3660597, 'parent_partid': 30}, {'status': 'failed', 'failreason': 'No path found', 'partid': 122, 'amount_msat': 1980677, 'parent_partid': 58}, {'status': 'pending', 'failreason': 'No path found', 'partid': 155, 'amount_msat': 1980677, 'parent_partid': 122}, {'status': 'pending', 'failreason': 'No path found', 'partid': 325, 'amount_msat': 1003890, 'parent_partid': 155}, {'status': 'pending', 'failreason': 'No path found', 'partid': 393, 'amount_msat': 536229, 'parent_partid': 325}, {'status': 'failed', 'failreason': 'No path found', 'partid': 500, 'amount_msat': 248089, 'parent_partid': 393}, {'status': 'pending', 'failreason': 'No path found', 'partid': 918, 'amount_msat': 248089, 'parent_partid': 500}, {'status': 'pending', 'failreason': 'No path found', 'partid': 1439, 'amount_msat': 124372, 'parent_partid': 918}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1878, 'amount_msat': 66928, 'parent_partid': 1439}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1945, 'amount_msat': 66928, 'parent_partid': 1878}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1879, 'amount_msat': 57444, 'parent_partid': 1439}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1440, 'amount_msat': 123717, 'parent_partid': 918}, {'status': 'pending', 'failreason': 'No path found', 'partid': 1578, 'amount_msat': 123717, 'parent_partid': 1440}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1746, 'amount_msat': 63506, 'parent_partid': 1578}, {'status': 'failed', 'failreason': 'No path found', 'partid': 2051, 'amount_msat': 63506, 'parent_partid': 1746}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1747, 'amount_msat': 60211, 'parent_partid': 1578}, {'status': 'pending', 'failreason': 'No path found', 'partid': 501, 'amount_msat': 288140, 'parent_partid': 393}, {'status': 'pending', 'failreason': 'No path found', 'partid': 919, 'amount_msat': 137401, 'parent_partid': 501}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1070, 'amount_msat': 69009, 'parent_partid': 919}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1640, 'amount_msat': 69009, 'parent_partid': 1070}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1071, 'amount_msat': 68392, 'parent_partid': 919}, {'status': 'failed', 'failreason': 'No path found', 'partid': 920, 'amount_msat': 150739, 'parent_partid': 501}, {'status': 'pending', 'failreason': 'No path found', 'partid': 1072, 'amount_msat': 150739, 'parent_partid': 920}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1272, 'amount_msat': 68287, 'parent_partid': 1072}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1520, 'amount_msat': 68287, 'parent_partid': 1272}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1273, 'amount_msat': 82452, 'parent_partid': 1072}, {'status': 'failed', 'failreason': 'No path found', 'partid': 394, 'amount_msat': 467661, 'parent_partid': 325}, {'status': 'pending', 'failreason': 'No path found', 'partid': 502, 'amount_msat': 467661, 'parent_partid': 394}, {'status': 'pending', 'failreason': 'No path found', 'partid': 921, 'amount_msat': 242003, 'parent_partid': 502}, {'status': 'pending', 'failreason': 'No path found', 'partid': 1441, 'amount_msat': 115729, 'parent_partid': 921}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1880, 'amount_msat': 58270, 'parent_partid': 1441}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1946, 'amount_msat': 58270, 'parent_partid': 1880}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1881, 'amount_msat': 57459, 'parent_partid': 1441}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1442, 'amount_msat': 126274, 'parent_partid': 921}, {'status': 'pending', 'failreason': 'No path found', 'partid': 1882, 'amount_msat': 126274, 'parent_partid': 1442}, {'status': 'failed', 'failreason': 'No path found', 'partid': 2084, 'amount_msat': 66011, 'parent_partid': 1882}, {'status': 'failed', 'failreason': 'No path found', 'partid': 2109, 'amount_msat': 66011, 'parent_partid': 2084}, {'status': 'failed', 'failreason': 'No path found', 'partid': 2085, 'amount_msat': 60263, 'parent_partid': 1882}, {'status': 'failed', 'failreason': 'No path found', 'partid': 922, 'amount_msat': 225658, 'parent_partid': 502}, {'status': 'pending', 'failreason': 'No path found', 'partid': 1443, 'amount_msat': 225658, 'parent_partid': 922}, {'status': 'pending', 'failreason': 'No path found', 'partid': 1579, 'amount_msat': 117424, 'parent_partid': 1443}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1974, 'amount_msat': 62393, 'parent_partid': 1579}, {'status': 'failed', 'failreason': 'No path found', 'partid': 2126, 'amount_msat': 62393, 'parent_partid': 1974}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1975, 'amount_msat': 55031, 'parent_partid': 1579}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1580, 'amount_msat': 108234, 'parent_partid': 1443}, {'status': 'pending', 'failreason': 'No path found', 'partid': 1976, 'amount_msat': 108234, 'parent_partid': 1580}, {'status': 'failed', 'failreason': 'No path found', 'partid': 2127, 'amount_msat': 54194, 'parent_partid': 1976}, {'status': 'failed', 'failreason': 'No path found', 'partid': 2128, 'amount_msat': 54040, 'parent_partid': 1976}, {'status': 'failed', 'failreason': 'No path found', 'partid': 2175, 'amount_msat': 54040, 'parent_partid': 2128}, {'status': 'failed', 'failreason': 'No path found', 'partid': 326, 'amount_msat': 976787, 'parent_partid': 155}, {'status': 'pending', 'failreason': 'No path found', 'partid': 395, 'amount_msat': 976787, 'parent_partid': 326}, {'status': 'pending', 'failreason': 'No path found', 'partid': 503, 'amount_msat': 474071, 'parent_partid': 395}, {'status': 'failed', 'failreason': 'No path found', 'partid': 634, 'amount_msat': 215595, 'parent_partid': 503}, {'status': 'pending', 'failreason': 'No path found', 'partid': 802, 'amount_msat': 215595, 'parent_partid': 634}, {'status': 'pending', 'failreason': 'No path found', 'partid': 1371, 'amount_msat': 112948, 'parent_partid': 802}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1556, 'amount_msat': 54070, 'parent_partid': 1371}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1742, 'amount_msat': 54070, 'parent_partid': 1556}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1557, 'amount_msat': 58878, 'parent_partid': 1371}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1372, 'amount_msat': 102647, 'parent_partid': 802}, {'status': 'pending', 'failreason': 'No path found', 'partid': 1558, 'amount_msat': 102647, 'parent_partid': 1372}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1965, 'amount_msat': 49624, 'parent_partid': 1558}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1966, 'amount_msat': 53023, 'parent_partid': 1558}, {'status': 'failed', 'failreason': 'No path found', 'partid': 2032, 'amount_msat': 53023, 'parent_partid': 1966}, {'status': 'pending', 'failreason': 'No path found', 'partid': 635, 'amount_msat': 258476, 'parent_partid': 503}, {'status': 'pending', 'failreason': 'No path found', 'partid': 803, 'amount_msat': 120654, 'parent_partid': 635}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1373, 'amount_msat': 60554, 'parent_partid': 803}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1374, 'amount_msat': 60100, 'parent_partid': 803}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1848, 'amount_msat': 60100, 'parent_partid': 1374}, {'status': 'failed', 'failreason': 'No path found', 'partid': 804, 'amount_msat': 137822, 'parent_partid': 635}, {'status': 'pending', 'failreason': 'No path found', 'partid': 1375, 'amount_msat': 137822, 'parent_partid': 804}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1559, 'amount_msat': 69716, 'parent_partid': 1375}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1560, 'amount_msat': 68106, 'parent_partid': 1375}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1967, 'amount_msat': 68106, 'parent_partid': 1560}, {'status': 'failed', 'failreason': 'No path found', 'partid': 504, 'amount_msat': 502716, 'parent_partid': 395}, {'status': 'pending', 'failreason': 'No path found', 'partid': 636, 'amount_msat': 502716, 'parent_partid': 504}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1142, 'amount_msat': 261754, 'parent_partid': 636}, {'status': 'pending', 'failreason': 'No path found', 'partid': 1677, 'amount_msat': 261754, 'parent_partid': 1142}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1778, 'amount_msat': 123357, 'parent_partid': 1677}, {'status': 'pending', 'failreason': 'No path found', 'partid': 1927, 'amount_msat': 123357, 'parent_partid': 1778}, {'status': 'failed', 'failreason': 'No path found', 'partid': 2026, 'amount_msat': 65267, 'parent_partid': 1927}, {'status': 'failed', 'failreason': 'No path found', 'partid': 2146, 'amount_msat': 65267, 'parent_partid': 2026}, {'status': 'failed', 'failreason': 'No path found', 'partid': 2027, 'amount_msat': 58090, 'parent_partid': 1927}, {'status': 'pending', 'failreason': 'No path found', 'partid': 1779, 'amount_msat': 138397, 'parent_partid': 1677}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1928, 'amount_msat': 72290, 'parent_partid': 1779}, {'status': 'failed', 'failreason': 'No path found', 'partid': 2118, 'amount_msat': 72290, 'parent_partid': 1928}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1929, 'amount_msat': 66107, 'parent_partid': 1779}, {'status': 'pending', 'failreason': 'No path found', 'partid': 1143, 'amount_msat': 240962, 'parent_partid': 636}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1678, 'amount_msat': 121178, 'parent_partid': 1143}, {'status': 'pending', 'failreason': 'No path found', 'partid': 1780, 'amount_msat': 121178, 'parent_partid': 1678}, {'status': 'failed', 'failreason': 'No path found', 'partid': 2057, 'amount_msat': 56068, 'parent_partid': 1780}, {'status': 'failed', 'failreason': 'No path found', 'partid': 2058, 'amount_msat': 65110, 'parent_partid': 1780}, {'status': 'failed', 'failreason': 'No path found', 'partid': 2157, 'amount_msat': 65110, 'parent_partid': 2058}, {'status': 'pending', 'failreason': 'No path found', 'partid': 1679, 'amount_msat': 119784, 'parent_partid': 1143}, {'status': 'failed', 'failreason': 'No path found', 'partid': 2009, 'amount_msat': 61485, 'parent_partid': 1679}, {'status': 'failed', 'failreason': 'No path found', 'partid': 2010, 'amount_msat': 58299, 'parent_partid': 1679}, {'status': 'failed', 'failreason': 'No path found', 'partid': 2143, 'amount_msat': 58299, 'parent_partid': 2010}, {'status': 'pending', 'failreason': 'No path found', 'partid': 123, 'amount_msat': 1679920, 'parent_partid': 58}, {'status': 'failed', 'failreason': 'No path found', 'partid': 156, 'amount_msat': 820769, 'parent_partid': 123}, {'status': 'pending', 'failreason': 'No path found', 'partid': 203, 'amount_msat': 820769, 'parent_partid': 156}, {'status': 'failed', 'failreason': 'No path found', 'partid': 284, 'amount_msat': 375125, 'parent_partid': 203}, {'status': 'pending', 'failreason': 'No path found', 'partid': 364, 'amount_msat': 375125, 'parent_partid': 284}, {'status': 'failed', 'failreason': 'No path found', 'partid': 722, 'amount_msat': 198739, 'parent_partid': 364}, {'status': 'pending', 'failreason': 'No path found', 'partid': 857, 'amount_msat': 198739, 'parent_partid': 722}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1412, 'amount_msat': 92398, 'parent_partid': 857}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1570, 'amount_msat': 92398, 'parent_partid': 1412}, {'status': 'pending', 'failreason': 'No path found', 'partid': 1413, 'amount_msat': 106341, 'parent_partid': 857}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1571, 'amount_msat': 54375, 'parent_partid': 1413}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1572, 'amount_msat': 51966, 'parent_partid': 1413}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1744, 'amount_msat': 51966, 'parent_partid': 1572}, {'status': 'pending', 'failreason': 'No path found', 'partid': 723, 'amount_msat': 176386, 'parent_partid': 364}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1194, 'amount_msat': 92485, 'parent_partid': 723}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1701, 'amount_msat': 92485, 'parent_partid': 1194}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1195, 'amount_msat': 83901, 'parent_partid': 723}, {'status': 'pending', 'failreason': 'No path found', 'partid': 285, 'amount_msat': 445644, 'parent_partid': 203}, {'status': 'failed', 'failreason': 'No path found', 'partid': 578, 'amount_msat': 239562, 'parent_partid': 285}, {'status': 'pending', 'failreason': 'No path found', 'partid': 983, 'amount_msat': 239562, 'parent_partid': 578}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1112, 'amount_msat': 118770, 'parent_partid': 983}, {'status': 'pending', 'failreason': 'No path found', 'partid': 1662, 'amount_msat': 118770, 'parent_partid': 1112}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1772, 'amount_msat': 56761, 'parent_partid': 1662}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1923, 'amount_msat': 56761, 'parent_partid': 1772}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1773, 'amount_msat': 62009, 'parent_partid': 1662}, {'status': 'pending', 'failreason': 'No path found', 'partid': 1113, 'amount_msat': 120792, 'parent_partid': 983}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1663, 'amount_msat': 62912, 'parent_partid': 1113}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1664, 'amount_msat': 57880, 'parent_partid': 1113}, {'status': 'failed', 'failreason': 'No path found', 'partid': 2004, 'amount_msat': 57880, 'parent_partid': 1664}, {'status': 'pending', 'failreason': 'No path found', 'partid': 579, 'amount_msat': 206082, 'parent_partid': 285}, {'status': 'failed', 'failreason': 'No path found', 'partid': 679, 'amount_msat': 93733, 'parent_partid': 579}, {'status': 'failed', 'failreason': 'No path found', 'partid': 680, 'amount_msat': 112349, 'parent_partid': 579}, {'status': 'pending', 'failreason': 'No path found', 'partid': 830, 'amount_msat': 112349, 'parent_partid': 680}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1394, 'amount_msat': 51109, 'parent_partid': 830}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1855, 'amount_msat': 51109, 'parent_partid': 1394}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1395, 'amount_msat': 61240, 'parent_partid': 830}, {'status': 'pending', 'failreason': 'No path found', 'partid': 157, 'amount_msat': 859151, 'parent_partid': 123}, {'status': 'failed', 'failreason': 'No path found', 'partid': 204, 'amount_msat': 398859, 'parent_partid': 157}, {'status': 'pending', 'failreason': 'No path found', 'partid': 423, 'amount_msat': 398859, 'parent_partid': 204}, {'status': 'failed', 'failreason': 'No path found', 'partid': 760, 'amount_msat': 217507, 'parent_partid': 423}, {'status': 'pending', 'failreason': 'No path found', 'partid': 877, 'amount_msat': 217507, 'parent_partid': 760}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1050, 'amount_msat': 117427, 'parent_partid': 877}, {'status': 'pending', 'failreason': 'No path found', 'partid': 1630, 'amount_msat': 117427, 'parent_partid': 1050}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1994, 'amount_msat': 60333, 'parent_partid': 1630}, {'status': 'failed', 'failreason': 'No path found', 'partid': 2138, 'amount_msat': 60333, 'parent_partid': 1994}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1995, 'amount_msat': 57094, 'parent_partid': 1630}, {'status': 'pending', 'failreason': 'No path found', 'partid': 1051, 'amount_msat': 100080, 'parent_partid': 877}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1631, 'amount_msat': 52636, 'parent_partid': 1051}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1632, 'amount_msat': 47444, 'parent_partid': 1051}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1766, 'amount_msat': 47444, 'parent_partid': 1632}, {'status': 'pending', 'failreason': 'No path found', 'partid': 761, 'amount_msat': 181352, 'parent_partid': 423}, {'status': 'failed', 'failreason': 'No path found', 'partid': 878, 'amount_msat': 84661, 'parent_partid': 761}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1052, 'amount_msat': 84661, 'parent_partid': 878}, {'status': 'failed', 'failreason': 'No path found', 'partid': 879, 'amount_msat': 96691, 'parent_partid': 761}, {'status': 'pending', 'failreason': 'No path found', 'partid': 205, 'amount_msat': 460292, 'parent_partid': 157}, {'status': 'failed', 'failreason': 'No path found', 'partid': 286, 'amount_msat': 237483, 'parent_partid': 205}, {'status': 'pending', 'failreason': 'No path found', 'partid': 580, 'amount_msat': 237483, 'parent_partid': 286}, {'status': 'pending', 'failreason': 'No path found', 'partid': 681, 'amount_msat': 107034, 'parent_partid': 580}, {'status': 'failed', 'failreason': 'No path found', 'partid': 831, 'amount_msat': 51275, 'parent_partid': 681}, {'status': 'failed', 'failreason': 'No path found', 'partid': 832, 'amount_msat': 55759, 'parent_partid': 681}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1396, 'amount_msat': 55759, 'parent_partid': 832}, {'status': 'failed', 'failreason': 'No path found', 'partid': 682, 'amount_msat': 130449, 'parent_partid': 580}, {'status': 'pending', 'failreason': 'No path found', 'partid': 833, 'amount_msat': 130449, 'parent_partid': 682}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1397, 'amount_msat': 64221, 'parent_partid': 833}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1398, 'amount_msat': 66228, 'parent_partid': 833}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1856, 'amount_msat': 66228, 'parent_partid': 1398}, {'status': 'pending', 'failreason': 'No path found', 'partid': 287, 'amount_msat': 222809, 'parent_partid': 205}, {'status': 'pending', 'failreason': 'No path found', 'partid': 581, 'amount_msat': 109435, 'parent_partid': 287}, {'status': 'failed', 'failreason': 'No path found', 'partid': 984, 'amount_msat': 56224, 'parent_partid': 581}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1483, 'amount_msat': 56224, 'parent_partid': 984}, {'status': 'failed', 'failreason': 'No path found', 'partid': 985, 'amount_msat': 53211, 'parent_partid': 581}, {'status': 'failed', 'failreason': 'No path found', 'partid': 582, 'amount_msat': 113374, 'parent_partid': 287}, {'status': 'pending', 'failreason': 'No path found', 'partid': 683, 'amount_msat': 113374, 'parent_partid': 582}, {'status': 'failed', 'failreason': 'No path found', 'partid': 834, 'amount_msat': 53275, 'parent_partid': 683}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1399, 'amount_msat': 53275, 'parent_partid': 834}, {'status': 'failed', 'failreason': 'No path found', 'partid': 835, 'amount_msat': 60099, 'parent_partid': 683}, {'status': 'pending', 'failreason': 'No path found', 'partid': 31, 'amount_msat': 3163177, 'parent_partid': 22}, {'status': 'pending', 'failreason': 'No path found', 'partid': 59, 'amount_msat': 1709313, 'parent_partid': 31}, {'status': 'failed', 'failreason': 'No path found', 'partid': 72, 'amount_msat': 895721, 'parent_partid': 59}, {'status': 'pending', 'failreason': 'No path found', 'partid': 164, 'amount_msat': 895721, 'parent_partid': 72}, {'status': 'pending', 'failreason': 'No path found', 'partid': 333, 'amount_msat': 420920, 'parent_partid': 164}, {'status': 'failed', 'failreason': 'No path found', 'partid': 402, 'amount_msat': 196580, 'parent_partid': 333}, {'status': 'pending', 'failreason': 'No path found', 'partid': 508, 'amount_msat': 196580, 'parent_partid': 402}, {'status': 'failed', 'failreason': 'No path found', 'partid': 641, 'amount_msat': 96953, 'parent_partid': 508}, {'status': 'failed', 'failreason': 'No path found', 'partid': 642, 'amount_msat': 99627, 'parent_partid': 508}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1147, 'amount_msat': 99627, 'parent_partid': 642}, {'status': 'pending', 'failreason': 'No path found', 'partid': 403, 'amount_msat': 224340, 'parent_partid': 333}, {'status': 'pending', 'failreason': 'No path found', 'partid': 749, 'amount_msat': 122279, 'parent_partid': 403}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1213, 'amount_msat': 64968, 'parent_partid': 749}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1214, 'amount_msat': 57311, 'parent_partid': 749}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1340, 'amount_msat': 57311, 'parent_partid': 1214}, {'status': 'failed', 'failreason': 'No path found', 'partid': 750, 'amount_msat': 102061, 'parent_partid': 403}, {'status': 'pending', 'failreason': 'No path found', 'partid': 1215, 'amount_msat': 102061, 'parent_partid': 750}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1341, 'amount_msat': 45932, 'parent_partid': 1215}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1342, 'amount_msat': 56129, 'parent_partid': 1215}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1834, 'amount_msat': 56129, 'parent_partid': 1342}, {'status': 'failed', 'failreason': 'No path found', 'partid': 334, 'amount_msat': 474801, 'parent_partid': 164}, {'status': 'pending', 'failreason': 'No path found', 'partid': 620, 'amount_msat': 474801, 'parent_partid': 334}, {'status': 'pending', 'failreason': 'No path found', 'partid': 1019, 'amount_msat': 241460, 'parent_partid': 620}, {'status': 'pending', 'failreason': 'No path found', 'partid': 1133, 'amount_msat': 113109, 'parent_partid': 1019}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1673, 'amount_msat': 59729, 'parent_partid': 1133}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1674, 'amount_msat': 53380, 'parent_partid': 1133}, {'status': 'failed', 'failreason': 'No path found', 'partid': 2006, 'amount_msat': 53380, 'parent_partid': 1674}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1134, 'amount_msat': 128351, 'parent_partid': 1019}, {'status': 'pending', 'failreason': 'No path found', 'partid': 1307, 'amount_msat': 128351, 'parent_partid': 1134}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1813, 'amount_msat': 66401, 'parent_partid': 1307}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1814, 'amount_msat': 61950, 'parent_partid': 1307}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1932, 'amount_msat': 61950, 'parent_partid': 1814}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1020, 'amount_msat': 233341, 'parent_partid': 620}, {'status': 'pending', 'failreason': 'No path found', 'partid': 1510, 'amount_msat': 233341, 'parent_partid': 1020}, {'status': 'pending', 'failreason': 'No path found', 'partid': 1913, 'amount_msat': 121421, 'parent_partid': 1510}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1952, 'amount_msat': 66640, 'parent_partid': 1913}, {'status': 'failed', 'failreason': 'No path found', 'partid': 2120, 'amount_msat': 66640, 'parent_partid': 1952}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1953, 'amount_msat': 54781, 'parent_partid': 1913}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1914, 'amount_msat': 111920, 'parent_partid': 1510}, {'status': 'pending', 'failreason': 'No path found', 'partid': 2099, 'amount_msat': 111920, 'parent_partid': 1914}, {'status': 'failed', 'failreason': 'No path found', 'partid': 2113, 'amount_msat': 51953, 'parent_partid': 2099}, {'status': 'failed', 'failreason': 'No path found', 'partid': 2114, 'amount_msat': 59967, 'parent_partid': 2099}, {'status': 'failed', 'failreason': 'No path found', 'partid': 2172, 'amount_msat': 59967, 'parent_partid': 2114}, {'status': 'pending', 'failreason': 'No path found', 'partid': 73, 'amount_msat': 813592, 'parent_partid': 59}, {'status': 'failed', 'failreason': 'No path found', 'partid': 96, 'amount_msat': 402948, 'parent_partid': 73}, {'status': 'pending', 'failreason': 'No path found', 'partid': 225, 'amount_msat': 402948, 'parent_partid': 96}, {'status': 'pending', 'failreason': 'No path found', 'partid': 445, 'amount_msat': 213475, 'parent_partid': 225}, {'status': 'failed', 'failreason': 'No path found', 'partid': 778, 'amount_msat': 96141, 'parent_partid': 445}, {'status': 'failed', 'failreason': 'No path found', 'partid': 888, 'amount_msat': 96141, 'parent_partid': 778}, {'status': 'pending', 'failreason': 'No path found', 'partid': 779, 'amount_msat': 117334, 'parent_partid': 445}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1236, 'amount_msat': 57027, 'parent_partid': 779}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1719, 'amount_msat': 57027, 'parent_partid': 1236}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1237, 'amount_msat': 60307, 'parent_partid': 779}, {'status': 'failed', 'failreason': 'No path found', 'partid': 446, 'amount_msat': 189473, 'parent_partid': 225}, {'status': 'pending', 'failreason': 'No path found', 'partid': 543, 'amount_msat': 189473, 'parent_partid': 446}, {'status': 'failed', 'failreason': 'No path found', 'partid': 668, 'amount_msat': 93706, 'parent_partid': 543}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1162, 'amount_msat': 93706, 'parent_partid': 668}, {'status': 'failed', 'failreason': 'No path found', 'partid': 669, 'amount_msat': 95767, 'parent_partid': 543}, {'status': 'pending', 'failreason': 'No path found', 'partid': 97, 'amount_msat': 410644, 'parent_partid': 73}, {'status': 'pending', 'failreason': 'No path found', 'partid': 133, 'amount_msat': 209817, 'parent_partid': 97}, {'status': 'failed', 'failreason': 'No path found', 'partid': 176, 'amount_msat': 114299, 'parent_partid': 133}, {'status': 'pending', 'failreason': 'No path found', 'partid': 345, 'amount_msat': 114299, 'parent_partid': 176}, {'status': 'failed', 'failreason': 'No path found', 'partid': 627, 'amount_msat': 60980, 'parent_partid': 345}, {'status': 'failed', 'failreason': 'No path found', 'partid': 628, 'amount_msat': 53319, 'parent_partid': 345}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1026, 'amount_msat': 53319, 'parent_partid': 628}, {'status': 'failed', 'failreason': 'No path found', 'partid': 177, 'amount_msat': 95518, 'parent_partid': 133}, {'status': 'failed', 'failreason': 'No path found', 'partid': 134, 'amount_msat': 200827, 'parent_partid': 97}, {'status': 'pending', 'failreason': 'No path found', 'partid': 316, 'amount_msat': 200827, 'parent_partid': 134}, {'status': 'failed', 'failreason': 'No path found', 'partid': 385, 'amount_msat': 99753, 'parent_partid': 316}, {'status': 'failed', 'failreason': 'No path found', 'partid': 386, 'amount_msat': 101074, 'parent_partid': 316}, {'status': 'pending', 'failreason': 'No path found', 'partid': 736, 'amount_msat': 101074, 'parent_partid': 386}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1202, 'amount_msat': 46180, 'parent_partid': 736}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1703, 'amount_msat': 46180, 'parent_partid': 1202}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1203, 'amount_msat': 54894, 'parent_partid': 736}, {'status': 'failed', 'failreason': 'No path found', 'partid': 60, 'amount_msat': 1453864, 'parent_partid': 31}, {'status': 'pending', 'failreason': 'No path found', 'partid': 124, 'amount_msat': 1453864, 'parent_partid': 60}, {'status': 'failed', 'failreason': 'No path found', 'partid': 244, 'amount_msat': 778915, 'parent_partid': 124}, {'status': 'pending', 'failreason': 'No path found', 'partid': 305, 'amount_msat': 778915, 'parent_partid': 244}, {'status': 'pending', 'failreason': 'No path found', 'partid': 601, 'amount_msat': 372070, 'parent_partid': 305}, {'status': 'pending', 'failreason': 'No path found', 'partid': 1003, 'amount_msat': 202720, 'parent_partid': 601}, {'status': 'pending', 'failreason': 'No path found', 'partid': 1495, 'amount_msat': 109886, 'parent_partid': 1003}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1597, 'amount_msat': 50251, 'parent_partid': 1495}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1598, 'amount_msat': 59635, 'parent_partid': 1495}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1750, 'amount_msat': 59635, 'parent_partid': 1598}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1496, 'amount_msat': 92834, 'parent_partid': 1003}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1599, 'amount_msat': 92834, 'parent_partid': 1496}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1004, 'amount_msat': 169350, 'parent_partid': 601}, {'status': 'pending', 'failreason': 'No path found', 'partid': 1124, 'amount_msat': 169350, 'parent_partid': 1004}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1300, 'amount_msat': 92099, 'parent_partid': 1124}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1812, 'amount_msat': 92099, 'parent_partid': 1300}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1301, 'amount_msat': 77251, 'parent_partid': 1124}, {'status': 'failed', 'failreason': 'No path found', 'partid': 602, 'amount_msat': 406845, 'parent_partid': 305}, {'status': 'pending', 'failreason': 'No path found', 'partid': 1005, 'amount_msat': 406845, 'parent_partid': 602}, {'status': 'pending', 'failreason': 'No path found', 'partid': 1125, 'amount_msat': 188152, 'parent_partid': 1005}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1302, 'amount_msat': 91322, 'parent_partid': 1125}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1530, 'amount_msat': 91322, 'parent_partid': 1302}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1303, 'amount_msat': 96830, 'parent_partid': 1125}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1126, 'amount_msat': 218693, 'parent_partid': 1005}, {'status': 'pending', 'failreason': 'No path found', 'partid': 1304, 'amount_msat': 218693, 'parent_partid': 1126}, {'status': 'pending', 'failreason': 'No path found', 'partid': 1531, 'amount_msat': 105400, 'parent_partid': 1304}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1732, 'amount_msat': 48666, 'parent_partid': 1531}, {'status': 'failed', 'failreason': 'No path found', 'partid': 2048, 'amount_msat': 48666, 'parent_partid': 1732}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1733, 'amount_msat': 56734, 'parent_partid': 1531}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1532, 'amount_msat': 113293, 'parent_partid': 1304}, {'status': 'pending', 'failreason': 'No path found', 'partid': 1734, 'amount_msat': 113293, 'parent_partid': 1532}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1917, 'amount_msat': 59226, 'parent_partid': 1734}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1918, 'amount_msat': 54067, 'parent_partid': 1734}, {'status': 'failed', 'failreason': 'No path found', 'partid': 2023, 'amount_msat': 54067, 'parent_partid': 1918}, {'status': 'pending', 'failreason': 'No path found', 'partid': 245, 'amount_msat': 674949, 'parent_partid': 124}, {'status': 'failed', 'failreason': 'No path found', 'partid': 306, 'amount_msat': 348382, 'parent_partid': 245}, {'status': 'pending', 'failreason': 'No path found', 'partid': 375, 'amount_msat': 348382, 'parent_partid': 306}, {'status': 'failed', 'failreason': 'No path found', 'partid': 488, 'amount_msat': 184586, 'parent_partid': 375}, {'status': 'pending', 'failreason': 'No path found', 'partid': 907, 'amount_msat': 184586, 'parent_partid': 488}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1431, 'amount_msat': 86079, 'parent_partid': 907}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1432, 'amount_msat': 98507, 'parent_partid': 907}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1577, 'amount_msat': 98507, 'parent_partid': 1432}, {'status': 'pending', 'failreason': 'No path found', 'partid': 489, 'amount_msat': 163796, 'parent_partid': 375}, {'status': 'failed', 'failreason': 'No path found', 'partid': 908, 'amount_msat': 86410, 'parent_partid': 489}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1065, 'amount_msat': 86410, 'parent_partid': 908}, {'status': 'failed', 'failreason': 'No path found', 'partid': 909, 'amount_msat': 77386, 'parent_partid': 489}, {'status': 'pending', 'failreason': 'No path found', 'partid': 307, 'amount_msat': 326567, 'parent_partid': 245}, {'status': 'failed', 'failreason': 'No path found', 'partid': 376, 'amount_msat': 159043, 'parent_partid': 307}, {'status': 'pending', 'failreason': 'No path found', 'partid': 730, 'amount_msat': 159043, 'parent_partid': 376}, {'status': 'failed', 'failreason': 'No path found', 'partid': 860, 'amount_msat': 76070, 'parent_partid': 730}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1414, 'amount_msat': 76070, 'parent_partid': 860}, {'status': 'failed', 'failreason': 'No path found', 'partid': 861, 'amount_msat': 82973, 'parent_partid': 730}, {'status': 'pending', 'failreason': 'No path found', 'partid': 377, 'amount_msat': 167524, 'parent_partid': 307}, {'status': 'failed', 'failreason': 'No path found', 'partid': 490, 'amount_msat': 80420, 'parent_partid': 377}, {'status': 'failed', 'failreason': 'No path found', 'partid': 910, 'amount_msat': 80420, 'parent_partid': 490}, {'status': 'failed', 'failreason': 'No path found', 'partid': 491, 'amount_msat': 87104, 'parent_partid': 377}, {'status': 'pending', 'failreason': 'No path found', 'partid': 15, 'amount_msat': 6788318, 'parent_partid': 7}, {'status': 'pending', 'failreason': 'No path found', 'partid': 23, 'amount_msat': 3653594, 'parent_partid': 15}, {'status': 'pending', 'failreason': 'No path found', 'partid': 45, 'amount_msat': 1861440, 'parent_partid': 23}, {'status': 'pending', 'failreason': 'No path found', 'partid': 85, 'amount_msat': 958835, 'parent_partid': 45}, {'status': 'failed', 'failreason': 'No path found', 'partid': 110, 'amount_msat': 438347, 'parent_partid': 85}, {'status': 'pending', 'failreason': 'No path found', 'partid': 234, 'amount_msat': 438347, 'parent_partid': 110}, {'status': 'failed', 'failreason': 'No path found', 'partid': 456, 'amount_msat': 223108, 'parent_partid': 234}, {'status': 'pending', 'failreason': 'No path found', 'partid': 552, 'amount_msat': 223108, 'parent_partid': 456}, {'status': 'failed', 'failreason': 'No path found', 'partid': 958, 'amount_msat': 101602, 'parent_partid': 552}, {'status': 'pending', 'failreason': 'No path found', 'partid': 1470, 'amount_msat': 101602, 'parent_partid': 958}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1899, 'amount_msat': 48962, 'parent_partid': 1470}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1900, 'amount_msat': 52640, 'parent_partid': 1470}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1948, 'amount_msat': 52640, 'parent_partid': 1900}, {'status': 'pending', 'failreason': 'No path found', 'partid': 959, 'amount_msat': 121506, 'parent_partid': 552}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1091, 'amount_msat': 63927, 'parent_partid': 959}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1092, 'amount_msat': 57579, 'parent_partid': 959}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1647, 'amount_msat': 57579, 'parent_partid': 1092}, {'status': 'pending', 'failreason': 'No path found', 'partid': 457, 'amount_msat': 215239, 'parent_partid': 234}, {'status': 'pending', 'failreason': 'No path found', 'partid': 787, 'amount_msat': 107052, 'parent_partid': 457}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1242, 'amount_msat': 50309, 'parent_partid': 787}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1358, 'amount_msat': 50309, 'parent_partid': 1242}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1243, 'amount_msat': 56743, 'parent_partid': 787}, {'status': 'failed', 'failreason': 'No path found', 'partid': 788, 'amount_msat': 108187, 'parent_partid': 457}, {'status': 'pending', 'failreason': 'No path found', 'partid': 1244, 'amount_msat': 108187, 'parent_partid': 788}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1359, 'amount_msat': 53380, 'parent_partid': 1244}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1360, 'amount_msat': 54807, 'parent_partid': 1244}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1844, 'amount_msat': 54807, 'parent_partid': 1360}, {'status': 'pending', 'failreason': 'No path found', 'partid': 111, 'amount_msat': 520488, 'parent_partid': 85}, {'status': 'failed', 'failreason': 'No path found', 'partid': 146, 'amount_msat': 265919, 'parent_partid': 111}, {'status': 'pending', 'failreason': 'No path found', 'partid': 321, 'amount_msat': 265919, 'parent_partid': 146}, {'status': 'pending', 'failreason': 'No path found', 'partid': 613, 'amount_msat': 123501, 'parent_partid': 321}, {'status': 'failed', 'failreason': 'No path found', 'partid': 701, 'amount_msat': 55820, 'parent_partid': 613}, {'status': 'failed', 'failreason': 'No path found', 'partid': 702, 'amount_msat': 67681, 'parent_partid': 613}, {'status': 'failed', 'failreason': 'No path found', 'partid': 849, 'amount_msat': 67681, 'parent_partid': 702}, {'status': 'failed', 'failreason': 'No path found', 'partid': 614, 'amount_msat': 142418, 'parent_partid': 321}, {'status': 'pending', 'failreason': 'No path found', 'partid': 703, 'amount_msat': 142418, 'parent_partid': 614}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1180, 'amount_msat': 70819, 'parent_partid': 703}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1694, 'amount_msat': 70819, 'parent_partid': 1180}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1181, 'amount_msat': 71599, 'parent_partid': 703}, {'status': 'pending', 'failreason': 'No path found', 'partid': 147, 'amount_msat': 254569, 'parent_partid': 111}, {'status': 'failed', 'failreason': 'No path found', 'partid': 192, 'amount_msat': 131799, 'parent_partid': 147}, {'status': 'pending', 'failreason': 'No path found', 'partid': 270, 'amount_msat': 131799, 'parent_partid': 192}, {'status': 'failed', 'failreason': 'No path found', 'partid': 354, 'amount_msat': 66290, 'parent_partid': 270}, {'status': 'failed', 'failreason': 'No path found', 'partid': 475, 'amount_msat': 66290, 'parent_partid': 354}, {'status': 'failed', 'failreason': 'No path found', 'partid': 355, 'amount_msat': 65509, 'parent_partid': 270}, {'status': 'pending', 'failreason': 'No path found', 'partid': 193, 'amount_msat': 122770, 'parent_partid': 147}, {'status': 'failed', 'failreason': 'No path found', 'partid': 271, 'amount_msat': 59301, 'parent_partid': 193}, {'status': 'failed', 'failreason': 'No path found', 'partid': 272, 'amount_msat': 63469, 'parent_partid': 193}, {'status': 'failed', 'failreason': 'No path found', 'partid': 571, 'amount_msat': 63469, 'parent_partid': 272}, {'status': 'failed', 'failreason': 'No path found', 'partid': 86, 'amount_msat': 902605, 'parent_partid': 45}, {'status': 'pending', 'failreason': 'No path found', 'partid': 112, 'amount_msat': 902605, 'parent_partid': 86}, {'status': 'pending', 'failreason': 'No path found', 'partid': 235, 'amount_msat': 455637, 'parent_partid': 112}, {'status': 'pending', 'failreason': 'No path found', 'partid': 299, 'amount_msat': 241424, 'parent_partid': 235}, {'status': 'pending', 'failreason': 'No path found', 'partid': 595, 'amount_msat': 122387, 'parent_partid': 299}, {'status': 'failed', 'failreason': 'No path found', 'partid': 996, 'amount_msat': 64994, 'parent_partid': 595}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1491, 'amount_msat': 64994, 'parent_partid': 996}, {'status': 'failed', 'failreason': 'No path found', 'partid': 997, 'amount_msat': 57393, 'parent_partid': 595}, {'status': 'failed', 'failreason': 'No path found', 'partid': 596, 'amount_msat': 119037, 'parent_partid': 299}, {'status': 'pending', 'failreason': 'No path found', 'partid': 691, 'amount_msat': 119037, 'parent_partid': 596}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1174, 'amount_msat': 60875, 'parent_partid': 691}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1328, 'amount_msat': 60875, 'parent_partid': 1174}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1175, 'amount_msat': 58162, 'parent_partid': 691}, {'status': 'failed', 'failreason': 'No path found', 'partid': 300, 'amount_msat': 214213, 'parent_partid': 235}, {'status': 'pending', 'failreason': 'No path found', 'partid': 371, 'amount_msat': 214213, 'parent_partid': 300}, {'status': 'failed', 'failreason': 'No path found', 'partid': 486, 'amount_msat': 117458, 'parent_partid': 371}, {'status': 'pending', 'failreason': 'No path found', 'partid': 906, 'amount_msat': 117458, 'parent_partid': 486}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1063, 'amount_msat': 60674, 'parent_partid': 906}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1064, 'amount_msat': 56784, 'parent_partid': 906}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1269, 'amount_msat': 56784, 'parent_partid': 1064}, {'status': 'failed', 'failreason': 'No path found', 'partid': 487, 'amount_msat': 96755, 'parent_partid': 371}, {'status': 'failed', 'failreason': 'No path found', 'partid': 236, 'amount_msat': 446968, 'parent_partid': 112}, {'status': 'pending', 'failreason': 'No path found', 'partid': 458, 'amount_msat': 446968, 'parent_partid': 236}, {'status': 'pending', 'failreason': 'No path found', 'partid': 553, 'amount_msat': 210111, 'parent_partid': 458}, {'status': 'failed', 'failreason': 'No path found', 'partid': 960, 'amount_msat': 101820, 'parent_partid': 553}, {'status': 'pending', 'failreason': 'No path found', 'partid': 1093, 'amount_msat': 101820, 'parent_partid': 960}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1648, 'amount_msat': 45836, 'parent_partid': 1093}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1999, 'amount_msat': 45836, 'parent_partid': 1648}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1649, 'amount_msat': 55984, 'parent_partid': 1093}, {'status': 'pending', 'failreason': 'No path found', 'partid': 961, 'amount_msat': 108291, 'parent_partid': 553}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1094, 'amount_msat': 58744, 'parent_partid': 961}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1650, 'amount_msat': 58744, 'parent_partid': 1094}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1095, 'amount_msat': 49547, 'parent_partid': 961}, {'status': 'failed', 'failreason': 'No path found', 'partid': 554, 'amount_msat': 236857, 'parent_partid': 458}, {'status': 'pending', 'failreason': 'No path found', 'partid': 675, 'amount_msat': 236857, 'parent_partid': 554}, {'status': 'pending', 'failreason': 'No path found', 'partid': 1167, 'amount_msat': 108672, 'parent_partid': 675}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1688, 'amount_msat': 48938, 'parent_partid': 1167}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1787, 'amount_msat': 48938, 'parent_partid': 1688}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1689, 'amount_msat': 59734, 'parent_partid': 1167}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1168, 'amount_msat': 128185, 'parent_partid': 675}, {'status': 'pending', 'failreason': 'No path found', 'partid': 1690, 'amount_msat': 128185, 'parent_partid': 1168}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1788, 'amount_msat': 64504, 'parent_partid': 1690}, {'status': 'failed', 'failreason': 'No path found', 'partid': 2062, 'amount_msat': 64504, 'parent_partid': 1788}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1789, 'amount_msat': 63681, 'parent_partid': 1690}, {'status': 'failed', 'failreason': 'No path found', 'partid': 46, 'amount_msat': 1792154, 'parent_partid': 23}, {'status': 'pending', 'failreason': 'No path found', 'partid': 87, 'amount_msat': 1792154, 'parent_partid': 46}, {'status': 'pending', 'failreason': 'No path found', 'partid': 171, 'amount_msat': 945978, 'parent_partid': 87}, {'status': 'pending', 'failreason': 'No path found', 'partid': 213, 'amount_msat': 495148, 'parent_partid': 171}, {'status': 'failed', 'failreason': 'No path found', 'partid': 432, 'amount_msat': 272298, 'parent_partid': 213}, {'status': 'pending', 'failreason': 'No path found', 'partid': 530, 'amount_msat': 272298, 'parent_partid': 432}, {'status': 'failed', 'failreason': 'No path found', 'partid': 662, 'amount_msat': 136019, 'parent_partid': 530}, {'status': 'pending', 'failreason': 'No path found', 'partid': 1159, 'amount_msat': 136019, 'parent_partid': 662}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1320, 'amount_msat': 70609, 'parent_partid': 1159}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1824, 'amount_msat': 70609, 'parent_partid': 1320}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1321, 'amount_msat': 65410, 'parent_partid': 1159}, {'status': 'pending', 'failreason': 'No path found', 'partid': 663, 'amount_msat': 136279, 'parent_partid': 530}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1160, 'amount_msat': 68334, 'parent_partid': 663}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1322, 'amount_msat': 68334, 'parent_partid': 1160}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1161, 'amount_msat': 67945, 'parent_partid': 663}, {'status': 'pending', 'failreason': 'No path found', 'partid': 433, 'amount_msat': 222850, 'parent_partid': 213}, {'status': 'failed', 'failreason': 'No path found', 'partid': 772, 'amount_msat': 107805, 'parent_partid': 433}, {'status': 'pending', 'failreason': 'No path found', 'partid': 1231, 'amount_msat': 107805, 'parent_partid': 772}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1717, 'amount_msat': 59232, 'parent_partid': 1231}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1718, 'amount_msat': 48573, 'parent_partid': 1231}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1797, 'amount_msat': 48573, 'parent_partid': 1718}, {'status': 'pending', 'failreason': 'No path found', 'partid': 773, 'amount_msat': 115045, 'parent_partid': 433}, {'status': 'failed', 'failreason': 'No path found', 'partid': 886, 'amount_msat': 58104, 'parent_partid': 773}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1054, 'amount_msat': 58104, 'parent_partid': 886}, {'status': 'failed', 'failreason': 'No path found', 'partid': 887, 'amount_msat': 56941, 'parent_partid': 773}, {'status': 'failed', 'failreason': 'No path found', 'partid': 214, 'amount_msat': 450830, 'parent_partid': 171}, {'status': 'pending', 'failreason': 'No path found', 'partid': 434, 'amount_msat': 450830, 'parent_partid': 214}, {'status': 'failed', 'failreason': 'No path found', 'partid': 774, 'amount_msat': 214574, 'parent_partid': 434}, {'status': 'pending', 'failreason': 'No path found', 'partid': 1232, 'amount_msat': 214574, 'parent_partid': 774}, {'status': 'pending', 'failreason': 'No path found', 'partid': 1353, 'amount_msat': 106209, 'parent_partid': 1232}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1546, 'amount_msat': 49861, 'parent_partid': 1353}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1741, 'amount_msat': 49861, 'parent_partid': 1546}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1547, 'amount_msat': 56348, 'parent_partid': 1353}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1354, 'amount_msat': 108365, 'parent_partid': 1232}, {'status': 'pending', 'failreason': 'No path found', 'partid': 1548, 'amount_msat': 108365, 'parent_partid': 1354}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1959, 'amount_msat': 59485, 'parent_partid': 1548}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1960, 'amount_msat': 48880, 'parent_partid': 1548}, {'status': 'failed', 'failreason': 'No path found', 'partid': 2121, 'amount_msat': 48880, 'parent_partid': 1960}, {'status': 'pending', 'failreason': 'No path found', 'partid': 775, 'amount_msat': 236256, 'parent_partid': 434}, {'status': 'pending', 'failreason': 'No path found', 'partid': 1233, 'amount_msat': 107628, 'parent_partid': 775}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1355, 'amount_msat': 51826, 'parent_partid': 1233}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1356, 'amount_msat': 55802, 'parent_partid': 1233}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1841, 'amount_msat': 55802, 'parent_partid': 1356}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1234, 'amount_msat': 128628, 'parent_partid': 775}, {'status': 'pending', 'failreason': 'No path found', 'partid': 1357, 'amount_msat': 128628, 'parent_partid': 1234}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1842, 'amount_msat': 61846, 'parent_partid': 1357}, {'status': 'failed', 'failreason': 'No path found', 'partid': 2073, 'amount_msat': 61846, 'parent_partid': 1842}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1843, 'amount_msat': 66782, 'parent_partid': 1357}, {'status': 'failed', 'failreason': 'No path found', 'partid': 172, 'amount_msat': 846176, 'parent_partid': 87}, {'status': 'pending', 'failreason': 'No path found', 'partid': 342, 'amount_msat': 846176, 'parent_partid': 172}, {'status': 'pending', 'failreason': 'No path found', 'partid': 409, 'amount_msat': 420558, 'parent_partid': 342}, {'status': 'failed', 'failreason': 'No path found', 'partid': 516, 'amount_msat': 190546, 'parent_partid': 409}, {'status': 'pending', 'failreason': 'No path found', 'partid': 929, 'amount_msat': 190546, 'parent_partid': 516}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1448, 'amount_msat': 91764, 'parent_partid': 929}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1885, 'amount_msat': 91764, 'parent_partid': 1448}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1449, 'amount_msat': 98782, 'parent_partid': 929}, {'status': 'pending', 'failreason': 'No path found', 'partid': 517, 'amount_msat': 230012, 'parent_partid': 409}, {'status': 'failed', 'failreason': 'No path found', 'partid': 930, 'amount_msat': 108688, 'parent_partid': 517}, {'status': 'pending', 'failreason': 'No path found', 'partid': 1079, 'amount_msat': 108688, 'parent_partid': 930}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1641, 'amount_msat': 59413, 'parent_partid': 1079}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1642, 'amount_msat': 49275, 'parent_partid': 1079}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1769, 'amount_msat': 49275, 'parent_partid': 1642}, {'status': 'pending', 'failreason': 'No path found', 'partid': 931, 'amount_msat': 121324, 'parent_partid': 517}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1080, 'amount_msat': 57215, 'parent_partid': 931}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1643, 'amount_msat': 57215, 'parent_partid': 1080}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1081, 'amount_msat': 64109, 'parent_partid': 931}, {'status': 'failed', 'failreason': 'No path found', 'partid': 410, 'amount_msat': 425618, 'parent_partid': 342}, {'status': 'pending', 'failreason': 'No path found', 'partid': 518, 'amount_msat': 425618, 'parent_partid': 410}, {'status': 'failed', 'failreason': 'No path found', 'partid': 932, 'amount_msat': 213667, 'parent_partid': 518}, {'status': 'pending', 'failreason': 'No path found', 'partid': 1450, 'amount_msat': 213667, 'parent_partid': 932}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1886, 'amount_msat': 96241, 'parent_partid': 1450}, {'status': 'failed', 'failreason': 'No path found', 'partid': 2086, 'amount_msat': 96241, 'parent_partid': 1886}, {'status': 'pending', 'failreason': 'No path found', 'partid': 1887, 'amount_msat': 117426, 'parent_partid': 1450}, {'status': 'failed', 'failreason': 'No path found', 'partid': 2087, 'amount_msat': 55479, 'parent_partid': 1887}, {'status': 'failed', 'failreason': 'No path found', 'partid': 2088, 'amount_msat': 61947, 'parent_partid': 1887}, {'status': 'failed', 'failreason': 'No path found', 'partid': 2110, 'amount_msat': 61947, 'parent_partid': 2088}, {'status': 'pending', 'failreason': 'No path found', 'partid': 933, 'amount_msat': 211951, 'parent_partid': 518}, {'status': 'pending', 'failreason': 'No path found', 'partid': 1451, 'amount_msat': 114640, 'parent_partid': 933}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1888, 'amount_msat': 61771, 'parent_partid': 1451}, {'status': 'failed', 'failreason': 'No path found', 'partid': 2089, 'amount_msat': 61771, 'parent_partid': 1888}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1889, 'amount_msat': 52869, 'parent_partid': 1451}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1452, 'amount_msat': 97311, 'parent_partid': 933}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1581, 'amount_msat': 97311, 'parent_partid': 1452}, {'status': 'failed', 'failreason': 'No path found', 'partid': 24, 'amount_msat': 3134724, 'parent_partid': 15}, {'status': 'pending', 'failreason': 'No path found', 'partid': 47, 'amount_msat': 3134724, 'parent_partid': 24}, {'status': 'failed', 'failreason': 'No path found', 'partid': 54, 'amount_msat': 1698585, 'parent_partid': 47}, {'status': 'pending', 'failreason': 'No path found', 'partid': 67, 'amount_msat': 1698585, 'parent_partid': 54}, {'status': 'pending', 'failreason': 'No path found', 'partid': 159, 'amount_msat': 880051, 'parent_partid': 67}, {'status': 'failed', 'failreason': 'No path found', 'partid': 206, 'amount_msat': 470430, 'parent_partid': 159}, {'status': 'pending', 'failreason': 'No path found', 'partid': 424, 'amount_msat': 470430, 'parent_partid': 206}, {'status': 'failed', 'failreason': 'No path found', 'partid': 762, 'amount_msat': 227032, 'parent_partid': 424}, {'status': 'pending', 'failreason': 'No path found', 'partid': 1223, 'amount_msat': 227032, 'parent_partid': 762}, {'status': 'pending', 'failreason': 'No path found', 'partid': 1349, 'amount_msat': 103979, 'parent_partid': 1223}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1837, 'amount_msat': 49706, 'parent_partid': 1349}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1838, 'amount_msat': 54273, 'parent_partid': 1349}, {'status': 'failed', 'failreason': 'No path found', 'partid': 2070, 'amount_msat': 54273, 'parent_partid': 1838}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1350, 'amount_msat': 123053, 'parent_partid': 1223}, {'status': 'pending', 'failreason': 'No path found', 'partid': 1839, 'amount_msat': 123053, 'parent_partid': 1350}, {'status': 'failed', 'failreason': 'No path found', 'partid': 2071, 'amount_msat': 59082, 'parent_partid': 1839}, {'status': 'failed', 'failreason': 'No path found', 'partid': 2072, 'amount_msat': 63971, 'parent_partid': 1839}, {'status': 'failed', 'failreason': 'No path found', 'partid': 2107, 'amount_msat': 63971, 'parent_partid': 2072}, {'status': 'pending', 'failreason': 'No path found', 'partid': 763, 'amount_msat': 243398, 'parent_partid': 424}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1224, 'amount_msat': 120613, 'parent_partid': 763}, {'status': 'pending', 'failreason': 'No path found', 'partid': 1711, 'amount_msat': 120613, 'parent_partid': 1224}, {'status': 'failed', 'failreason': 'No path found', 'partid': 2016, 'amount_msat': 65986, 'parent_partid': 1711}, {'status': 'failed', 'failreason': 'No path found', 'partid': 2041, 'amount_msat': 65986, 'parent_partid': 2016}, {'status': 'failed', 'failreason': 'No path found', 'partid': 2017, 'amount_msat': 54627, 'parent_partid': 1711}, {'status': 'pending', 'failreason': 'No path found', 'partid': 1225, 'amount_msat': 122785, 'parent_partid': 763}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1712, 'amount_msat': 63086, 'parent_partid': 1225}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1795, 'amount_msat': 63086, 'parent_partid': 1712}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1713, 'amount_msat': 59699, 'parent_partid': 1225}, {'status': 'pending', 'failreason': 'No path found', 'partid': 207, 'amount_msat': 409621, 'parent_partid': 159}, {'status': 'pending', 'failreason': 'No path found', 'partid': 425, 'amount_msat': 222067, 'parent_partid': 207}, {'status': 'failed', 'failreason': 'No path found', 'partid': 764, 'amount_msat': 118602, 'parent_partid': 425}, {'status': 'pending', 'failreason': 'No path found', 'partid': 1226, 'amount_msat': 118602, 'parent_partid': 764}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1351, 'amount_msat': 56822, 'parent_partid': 1226}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1352, 'amount_msat': 61780, 'parent_partid': 1226}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1840, 'amount_msat': 61780, 'parent_partid': 1352}, {'status': 'pending', 'failreason': 'No path found', 'partid': 765, 'amount_msat': 103465, 'parent_partid': 425}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1227, 'amount_msat': 53554, 'parent_partid': 765}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1228, 'amount_msat': 49911, 'parent_partid': 765}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1714, 'amount_msat': 49911, 'parent_partid': 1228}, {'status': 'failed', 'failreason': 'No path found', 'partid': 426, 'amount_msat': 187554, 'parent_partid': 207}, {'status': 'pending', 'failreason': 'No path found', 'partid': 766, 'amount_msat': 187554, 'parent_partid': 426}, {'status': 'failed', 'failreason': 'No path found', 'partid': 880, 'amount_msat': 101456, 'parent_partid': 766}, {'status': 'pending', 'failreason': 'No path found', 'partid': 1421, 'amount_msat': 101456, 'parent_partid': 880}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1574, 'amount_msat': 51467, 'parent_partid': 1421}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1745, 'amount_msat': 51467, 'parent_partid': 1574}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1575, 'amount_msat': 49989, 'parent_partid': 1421}, {'status': 'failed', 'failreason': 'No path found', 'partid': 881, 'amount_msat': 86098, 'parent_partid': 766}, {'status': 'failed', 'failreason': 'No path found', 'partid': 160, 'amount_msat': 818534, 'parent_partid': 67}, {'status': 'pending', 'failreason': 'No path found', 'partid': 329, 'amount_msat': 818534, 'parent_partid': 160}, {'status': 'failed', 'failreason': 'No path found', 'partid': 398, 'amount_msat': 390234, 'parent_partid': 329}, {'status': 'pending', 'failreason': 'No path found', 'partid': 745, 'amount_msat': 390234, 'parent_partid': 398}, {'status': 'failed', 'failreason': 'No path found', 'partid': 864, 'amount_msat': 181460, 'parent_partid': 745}, {'status': 'pending', 'failreason': 'No path found', 'partid': 1044, 'amount_msat': 181460, 'parent_partid': 864}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1626, 'amount_msat': 86862, 'parent_partid': 1044}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1764, 'amount_msat': 86862, 'parent_partid': 1626}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1627, 'amount_msat': 94598, 'parent_partid': 1044}, {'status': 'pending', 'failreason': 'No path found', 'partid': 865, 'amount_msat': 208774, 'parent_partid': 745}, {'status': 'pending', 'failreason': 'No path found', 'partid': 1045, 'amount_msat': 102781, 'parent_partid': 865}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1628, 'amount_msat': 56134, 'parent_partid': 1045}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1765, 'amount_msat': 56134, 'parent_partid': 1628}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1629, 'amount_msat': 46647, 'parent_partid': 1045}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1046, 'amount_msat': 105993, 'parent_partid': 865}, {'status': 'pending', 'failreason': 'No path found', 'partid': 1264, 'amount_msat': 105993, 'parent_partid': 1046}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1517, 'amount_msat': 54559, 'parent_partid': 1264}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1518, 'amount_msat': 51434, 'parent_partid': 1264}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1730, 'amount_msat': 51434, 'parent_partid': 1518}, {'status': 'pending', 'failreason': 'No path found', 'partid': 399, 'amount_msat': 428300, 'parent_partid': 329}, {'status': 'failed', 'failreason': 'No path found', 'partid': 506, 'amount_msat': 211565, 'parent_partid': 399}, {'status': 'pending', 'failreason': 'No path found', 'partid': 923, 'amount_msat': 211565, 'parent_partid': 506}, {'status': 'pending', 'failreason': 'No path found', 'partid': 1073, 'amount_msat': 116050, 'parent_partid': 923}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1274, 'amount_msat': 54445, 'parent_partid': 1073}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1804, 'amount_msat': 54445, 'parent_partid': 1274}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1275, 'amount_msat': 61605, 'parent_partid': 1073}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1074, 'amount_msat': 95515, 'parent_partid': 923}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1276, 'amount_msat': 95515, 'parent_partid': 1074}, {'status': 'pending', 'failreason': 'No path found', 'partid': 507, 'amount_msat': 216735, 'parent_partid': 399}, {'status': 'pending', 'failreason': 'No path found', 'partid': 639, 'amount_msat': 110170, 'parent_partid': 507}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1144, 'amount_msat': 51817, 'parent_partid': 639}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1680, 'amount_msat': 51817, 'parent_partid': 1144}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1145, 'amount_msat': 58353, 'parent_partid': 639}, {'status': 'failed', 'failreason': 'No path found', 'partid': 640, 'amount_msat': 106565, 'parent_partid': 507}, {'status': 'pending', 'failreason': 'No path found', 'partid': 1146, 'amount_msat': 106565, 'parent_partid': 640}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1310, 'amount_msat': 48168, 'parent_partid': 1146}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1817, 'amount_msat': 48168, 'parent_partid': 1310}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1311, 'amount_msat': 58397, 'parent_partid': 1146}, {'status': 'pending', 'failreason': 'No path found', 'partid': 55, 'amount_msat': 1436139, 'parent_partid': 47}, {'status': 'failed', 'failreason': 'No path found', 'partid': 68, 'amount_msat': 711492, 'parent_partid': 55}, {'status': 'pending', 'failreason': 'No path found', 'partid': 161, 'amount_msat': 711492, 'parent_partid': 68}, {'status': 'failed', 'failreason': 'No path found', 'partid': 208, 'amount_msat': 361538, 'parent_partid': 161}, {'status': 'pending', 'failreason': 'No path found', 'partid': 427, 'amount_msat': 361538, 'parent_partid': 208}, {'status': 'pending', 'failreason': 'No path found', 'partid': 767, 'amount_msat': 178214, 'parent_partid': 427}, {'status': 'failed', 'failreason': 'No path found', 'partid': 882, 'amount_msat': 87187, 'parent_partid': 767}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1053, 'amount_msat': 87187, 'parent_partid': 882}, {'status': 'failed', 'failreason': 'No path found', 'partid': 883, 'amount_msat': 91027, 'parent_partid': 767}, {'status': 'failed', 'failreason': 'No path found', 'partid': 768, 'amount_msat': 183324, 'parent_partid': 427}, {'status': 'pending', 'failreason': 'No path found', 'partid': 1229, 'amount_msat': 183324, 'parent_partid': 768}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1715, 'amount_msat': 90052, 'parent_partid': 1229}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1716, 'amount_msat': 93272, 'parent_partid': 1229}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1796, 'amount_msat': 93272, 'parent_partid': 1716}, {'status': 'pending', 'failreason': 'No path found', 'partid': 209, 'amount_msat': 349954, 'parent_partid': 161}, {'status': 'failed', 'failreason': 'No path found', 'partid': 288, 'amount_msat': 174126, 'parent_partid': 209}, {'status': 'pending', 'failreason': 'No path found', 'partid': 583, 'amount_msat': 174126, 'parent_partid': 288}, {'status': 'failed', 'failreason': 'No path found', 'partid': 684, 'amount_msat': 86530, 'parent_partid': 583}, {'status': 'failed', 'failreason': 'No path found', 'partid': 836, 'amount_msat': 86530, 'parent_partid': 684}, {'status': 'failed', 'failreason': 'No path found', 'partid': 685, 'amount_msat': 87596, 'parent_partid': 583}, {'status': 'pending', 'failreason': 'No path found', 'partid': 289, 'amount_msat': 175828, 'parent_partid': 209}, {'status': 'failed', 'failreason': 'No path found', 'partid': 365, 'amount_msat': 91599, 'parent_partid': 289}, {'status': 'failed', 'failreason': 'No path found', 'partid': 366, 'amount_msat': 84229, 'parent_partid': 289}, {'status': 'failed', 'failreason': 'No path found', 'partid': 724, 'amount_msat': 84229, 'parent_partid': 366}, {'status': 'pending', 'failreason': 'No path found', 'partid': 69, 'amount_msat': 724647, 'parent_partid': 55}, {'status': 'pending', 'failreason': 'No path found', 'partid': 93, 'amount_msat': 393097, 'parent_partid': 69}, {'status': 'failed', 'failreason': 'No path found', 'partid': 130, 'amount_msat': 178817, 'parent_partid': 93}, {'status': 'pending', 'failreason': 'No path found', 'partid': 173, 'amount_msat': 178817, 'parent_partid': 130}, {'status': 'failed', 'failreason': 'No path found', 'partid': 343, 'amount_msat': 80974, 'parent_partid': 173}, {'status': 'failed', 'failreason': 'No path found', 'partid': 344, 'amount_msat': 97843, 'parent_partid': 173}, {'status': 'failed', 'failreason': 'No path found', 'partid': 411, 'amount_msat': 97843, 'parent_partid': 344}, {'status': 'pending', 'failreason': 'No path found', 'partid': 131, 'amount_msat': 214280, 'parent_partid': 93}, {'status': 'failed', 'failreason': 'No path found', 'partid': 174, 'amount_msat': 111301, 'parent_partid': 131}, {'status': 'pending', 'failreason': 'No path found', 'partid': 253, 'amount_msat': 111301, 'parent_partid': 174}, {'status': 'failed', 'failreason': 'No path found', 'partid': 469, 'amount_msat': 55706, 'parent_partid': 253}, {'status': 'failed', 'failreason': 'No path found', 'partid': 470, 'amount_msat': 55595, 'parent_partid': 253}, {'status': 'failed', 'failreason': 'No path found', 'partid': 559, 'amount_msat': 55595, 'parent_partid': 470}, {'status': 'pending', 'failreason': 'No path found', 'partid': 175, 'amount_msat': 102979, 'parent_partid': 131}, {'status': 'failed', 'failreason': 'No path found', 'partid': 254, 'amount_msat': 53470, 'parent_partid': 175}, {'status': 'failed', 'failreason': 'No path found', 'partid': 471, 'amount_msat': 53470, 'parent_partid': 254}, {'status': 'failed', 'failreason': 'No path found', 'partid': 255, 'amount_msat': 49509, 'parent_partid': 175}, {'status': 'failed', 'failreason': 'No path found', 'partid': 94, 'amount_msat': 331550, 'parent_partid': 69}, {'status': 'pending', 'failreason': 'No path found', 'partid': 132, 'amount_msat': 331550, 'parent_partid': 94}, {'status': 'failed', 'failreason': 'No path found', 'partid': 314, 'amount_msat': 153138, 'parent_partid': 132}, {'status': 'pending', 'failreason': 'No path found', 'partid': 382, 'amount_msat': 153138, 'parent_partid': 314}, {'status': 'failed', 'failreason': 'No path found', 'partid': 734, 'amount_msat': 80360, 'parent_partid': 382}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1201, 'amount_msat': 80360, 'parent_partid': 734}, {'status': 'failed', 'failreason': 'No path found', 'partid': 735, 'amount_msat': 72778, 'parent_partid': 382}, {'status': 'pending', 'failreason': 'No path found', 'partid': 315, 'amount_msat': 178412, 'parent_partid': 132}, {'status': 'failed', 'failreason': 'No path found', 'partid': 383, 'amount_msat': 97106, 'parent_partid': 315}, {'status': 'failed', 'failreason': 'No path found', 'partid': 384, 'amount_msat': 81306, 'parent_partid': 315}, {'status': 'failed', 'failreason': 'No path found', 'partid': 496, 'amount_msat': 81306, 'parent_partid': 384}, {'status': 'failed', 'failreason': 'No path found', 'partid': 2, 'amount_msat': 24797864, 'parent_partid': 0}, {'status': 'pending', 'failreason': 'No path found', 'partid': 3, 'amount_msat': 24797864, 'parent_partid': 2}, {'status': 'failed', 'failreason': 'No path found', 'partid': 4, 'amount_msat': 12189568, 'parent_partid': 3}, {'status': 'pending', 'failreason': 'No path found', 'partid': 8, 'amount_msat': 12189568, 'parent_partid': 4}, {'status': 'pending', 'failreason': 'No path found', 'partid': 9, 'amount_msat': 6153317, 'parent_partid': 8}, {'status': 'failed', 'failreason': 'No path found', 'partid': 16, 'amount_msat': 2835438, 'parent_partid': 9}, {'status': 'pending', 'failreason': 'No path found', 'partid': 40, 'amount_msat': 2835438, 'parent_partid': 16}, {'status': 'failed', 'failreason': 'No path found', 'partid': 78, 'amount_msat': 1313297, 'parent_partid': 40}, {'status': 'pending', 'failreason': 'No path found', 'partid': 101, 'amount_msat': 1313297, 'parent_partid': 78}, {'status': 'failed', 'failreason': 'No path found', 'partid': 230, 'amount_msat': 602826, 'parent_partid': 101}, {'status': 'pending', 'failreason': 'No path found', 'partid': 453, 'amount_msat': 602826, 'parent_partid': 230}, {'status': 'failed', 'failreason': 'No path found', 'partid': 784, 'amount_msat': 277240, 'parent_partid': 453}, {'status': 'pending', 'failreason': 'No path found', 'partid': 1241, 'amount_msat': 277240, 'parent_partid': 784}, {'status': 'pending', 'failreason': 'No path found', 'partid': 1723, 'amount_msat': 133458, 'parent_partid': 1241}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1799, 'amount_msat': 73292, 'parent_partid': 1723}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1800, 'amount_msat': 60166, 'parent_partid': 1723}, {'status': 'failed', 'failreason': 'No path found', 'partid': 2064, 'amount_msat': 60166, 'parent_partid': 1800}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1724, 'amount_msat': 143782, 'parent_partid': 1241}, {'status': 'pending', 'failreason': 'No path found', 'partid': 2018, 'amount_msat': 143782, 'parent_partid': 1724}, {'status': 'failed', 'failreason': 'No path found', 'partid': 2042, 'amount_msat': 66860, 'parent_partid': 2018}, {'status': 'failed', 'failreason': 'No path found', 'partid': 2153, 'amount_msat': 66860, 'parent_partid': 2042}, {'status': 'failed', 'failreason': 'No path found', 'partid': 2043, 'amount_msat': 76922, 'parent_partid': 2018}, {'status': 'pending', 'failreason': 'No path found', 'partid': 785, 'amount_msat': 325586, 'parent_partid': 453}, {'status': 'pending', 'failreason': 'No path found', 'partid': 891, 'amount_msat': 178796, 'parent_partid': 785}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1425, 'amount_msat': 97609, 'parent_partid': 891}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1426, 'amount_msat': 81187, 'parent_partid': 891}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1866, 'amount_msat': 81187, 'parent_partid': 1426}, {'status': 'failed', 'failreason': 'No path found', 'partid': 892, 'amount_msat': 146790, 'parent_partid': 785}, {'status': 'pending', 'failreason': 'No path found', 'partid': 1056, 'amount_msat': 146790, 'parent_partid': 892}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1633, 'amount_msat': 76060, 'parent_partid': 1056}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1634, 'amount_msat': 70730, 'parent_partid': 1056}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1767, 'amount_msat': 70730, 'parent_partid': 1634}, {'status': 'pending', 'failreason': 'No path found', 'partid': 231, 'amount_msat': 710471, 'parent_partid': 101}, {'status': 'pending', 'failreason': 'No path found', 'partid': 295, 'amount_msat': 346630, 'parent_partid': 231}, {'status': 'failed', 'failreason': 'No path found', 'partid': 590, 'amount_msat': 183925, 'parent_partid': 295}, {'status': 'pending', 'failreason': 'No path found', 'partid': 991, 'amount_msat': 183925, 'parent_partid': 590}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1118, 'amount_msat': 96078, 'parent_partid': 991}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1668, 'amount_msat': 96078, 'parent_partid': 1118}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1119, 'amount_msat': 87847, 'parent_partid': 991}, {'status': 'pending', 'failreason': 'No path found', 'partid': 591, 'amount_msat': 162705, 'parent_partid': 295}, {'status': 'failed', 'failreason': 'No path found', 'partid': 688, 'amount_msat': 84192, 'parent_partid': 591}, {'status': 'failed', 'failreason': 'No path found', 'partid': 837, 'amount_msat': 84192, 'parent_partid': 688}, {'status': 'failed', 'failreason': 'No path found', 'partid': 689, 'amount_msat': 78513, 'parent_partid': 591}, {'status': 'failed', 'failreason': 'No path found', 'partid': 296, 'amount_msat': 363841, 'parent_partid': 231}, {'status': 'pending', 'failreason': 'No path found', 'partid': 370, 'amount_msat': 363841, 'parent_partid': 296}, {'status': 'failed', 'failreason': 'No path found', 'partid': 484, 'amount_msat': 166928, 'parent_partid': 370}, {'status': 'pending', 'failreason': 'No path found', 'partid': 905, 'amount_msat': 166928, 'parent_partid': 484}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1061, 'amount_msat': 84785, 'parent_partid': 905}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1062, 'amount_msat': 82143, 'parent_partid': 905}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1639, 'amount_msat': 82143, 'parent_partid': 1062}, {'status': 'pending', 'failreason': 'No path found', 'partid': 485, 'amount_msat': 196913, 'parent_partid': 370}, {'status': 'failed', 'failreason': 'No path found', 'partid': 630, 'amount_msat': 92214, 'parent_partid': 485}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1138, 'amount_msat': 92214, 'parent_partid': 630}, {'status': 'pending', 'failreason': 'No path found', 'partid': 631, 'amount_msat': 104699, 'parent_partid': 485}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1139, 'amount_msat': 48766, 'parent_partid': 631}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1140, 'amount_msat': 55933, 'parent_partid': 631}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1309, 'amount_msat': 55933, 'parent_partid': 1140}, {'status': 'pending', 'failreason': 'No path found', 'partid': 79, 'amount_msat': 1522141, 'parent_partid': 40}, {'status': 'failed', 'failreason': 'No path found', 'partid': 102, 'amount_msat': 823961, 'parent_partid': 79}, {'status': 'pending', 'failreason': 'No path found', 'partid': 232, 'amount_msat': 823961, 'parent_partid': 102}, {'status': 'failed', 'failreason': 'No path found', 'partid': 454, 'amount_msat': 393346, 'parent_partid': 232}, {'status': 'pending', 'failreason': 'No path found', 'partid': 786, 'amount_msat': 393346, 'parent_partid': 454}, {'status': 'pending', 'failreason': 'No path found', 'partid': 893, 'amount_msat': 215983, 'parent_partid': 786}, {'status': 'pending', 'failreason': 'No path found', 'partid': 1057, 'amount_msat': 118509, 'parent_partid': 893}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1635, 'amount_msat': 63096, 'parent_partid': 1057}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1636, 'amount_msat': 55413, 'parent_partid': 1057}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1768, 'amount_msat': 55413, 'parent_partid': 1636}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1058, 'amount_msat': 97474, 'parent_partid': 893}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1268, 'amount_msat': 97474, 'parent_partid': 1058}, {'status': 'failed', 'failreason': 'No path found', 'partid': 894, 'amount_msat': 177363, 'parent_partid': 786}, {'status': 'pending', 'failreason': 'No path found', 'partid': 1059, 'amount_msat': 177363, 'parent_partid': 894}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1637, 'amount_msat': 92814, 'parent_partid': 1059}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1638, 'amount_msat': 84549, 'parent_partid': 1059}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1996, 'amount_msat': 84549, 'parent_partid': 1638}, {'status': 'pending', 'failreason': 'No path found', 'partid': 455, 'amount_msat': 430615, 'parent_partid': 232}, {'status': 'failed', 'failreason': 'No path found', 'partid': 550, 'amount_msat': 229423, 'parent_partid': 455}, {'status': 'pending', 'failreason': 'No path found', 'partid': 674, 'amount_msat': 229423, 'parent_partid': 550}, {'status': 'failed', 'failreason': 'No path found', 'partid': 828, 'amount_msat': 106435, 'parent_partid': 674}, {'status': 'pending', 'failreason': 'No path found', 'partid': 1036, 'amount_msat': 106435, 'parent_partid': 828}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1258, 'amount_msat': 51450, 'parent_partid': 1036}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1729, 'amount_msat': 51450, 'parent_partid': 1258}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1259, 'amount_msat': 54985, 'parent_partid': 1036}, {'status': 'pending', 'failreason': 'No path found', 'partid': 829, 'amount_msat': 122988, 'parent_partid': 674}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1392, 'amount_msat': 57448, 'parent_partid': 829}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1854, 'amount_msat': 57448, 'parent_partid': 1392}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1393, 'amount_msat': 65540, 'parent_partid': 829}, {'status': 'pending', 'failreason': 'No path found', 'partid': 551, 'amount_msat': 201192, 'parent_partid': 455}, {'status': 'failed', 'failreason': 'No path found', 'partid': 956, 'amount_msat': 93025, 'parent_partid': 551}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1090, 'amount_msat': 93025, 'parent_partid': 956}, {'status': 'pending', 'failreason': 'No path found', 'partid': 957, 'amount_msat': 108167, 'parent_partid': 551}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1468, 'amount_msat': 52133, 'parent_partid': 957}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1898, 'amount_msat': 52133, 'parent_partid': 1468}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1469, 'amount_msat': 56034, 'parent_partid': 957}, {'status': 'pending', 'failreason': 'No path found', 'partid': 103, 'amount_msat': 698180, 'parent_partid': 79}, {'status': 'failed', 'failreason': 'No path found', 'partid': 136, 'amount_msat': 370452, 'parent_partid': 103}, {'status': 'pending', 'failreason': 'No path found', 'partid': 178, 'amount_msat': 370452, 'parent_partid': 136}, {'status': 'failed', 'failreason': 'No path found', 'partid': 412, 'amount_msat': 179994, 'parent_partid': 178}, {'status': 'pending', 'failreason': 'No path found', 'partid': 519, 'amount_msat': 179994, 'parent_partid': 412}, {'status': 'failed', 'failreason': 'No path found', 'partid': 649, 'amount_msat': 89462, 'parent_partid': 519}, {'status': 'failed', 'failreason': 'No path found', 'partid': 650, 'amount_msat': 90532, 'parent_partid': 519}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1153, 'amount_msat': 90532, 'parent_partid': 650}, {'status': 'pending', 'failreason': 'No path found', 'partid': 413, 'amount_msat': 190458, 'parent_partid': 178}, {'status': 'failed', 'failreason': 'No path found', 'partid': 520, 'amount_msat': 89663, 'parent_partid': 413}, {'status': 'failed', 'failreason': 'No path found', 'partid': 651, 'amount_msat': 89663, 'parent_partid': 520}, {'status': 'pending', 'failreason': 'No path found', 'partid': 521, 'amount_msat': 100795, 'parent_partid': 413}, {'status': 'failed', 'failreason': 'No path found', 'partid': 934, 'amount_msat': 55208, 'parent_partid': 521}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1453, 'amount_msat': 55208, 'parent_partid': 934}, {'status': 'failed', 'failreason': 'No path found', 'partid': 935, 'amount_msat': 45587, 'parent_partid': 521}, {'status': 'pending', 'failreason': 'No path found', 'partid': 137, 'amount_msat': 327728, 'parent_partid': 103}, {'status': 'pending', 'failreason': 'No path found', 'partid': 179, 'amount_msat': 174352, 'parent_partid': 137}, {'status': 'failed', 'failreason': 'No path found', 'partid': 256, 'amount_msat': 86509, 'parent_partid': 179}, {'status': 'failed', 'failreason': 'No path found', 'partid': 560, 'amount_msat': 86509, 'parent_partid': 256}, {'status': 'failed', 'failreason': 'No path found', 'partid': 257, 'amount_msat': 87843, 'parent_partid': 179}, {'status': 'failed', 'failreason': 'No path found', 'partid': 180, 'amount_msat': 153376, 'parent_partid': 137}, {'status': 'pending', 'failreason': 'No path found', 'partid': 258, 'amount_msat': 153376, 'parent_partid': 180}, {'status': 'failed', 'failreason': 'No path found', 'partid': 346, 'amount_msat': 73357, 'parent_partid': 258}, {'status': 'failed', 'failreason': 'No path found', 'partid': 472, 'amount_msat': 73357, 'parent_partid': 346}, {'status': 'failed', 'failreason': 'No path found', 'partid': 347, 'amount_msat': 80019, 'parent_partid': 258}, {'status': 'pending', 'failreason': 'No path found', 'partid': 17, 'amount_msat': 3317879, 'parent_partid': 9}, {'status': 'pending', 'failreason': 'No path found', 'partid': 25, 'amount_msat': 1552702, 'parent_partid': 17}, {'status': 'failed', 'failreason': 'No path found', 'partid': 34, 'amount_msat': 784945, 'parent_partid': 25}, {'status': 'pending', 'failreason': 'No path found', 'partid': 48, 'amount_msat': 784945, 'parent_partid': 34}, {'status': 'pending', 'failreason': 'No path found', 'partid': 113, 'amount_msat': 431390, 'parent_partid': 48}, {'status': 'pending', 'failreason': 'No path found', 'partid': 237, 'amount_msat': 217127, 'parent_partid': 113}, {'status': 'pending', 'failreason': 'No path found', 'partid': 459, 'amount_msat': 107872, 'parent_partid': 237}, {'status': 'failed', 'failreason': 'No path found', 'partid': 789, 'amount_msat': 57396, 'parent_partid': 459}, {'status': 'failed', 'failreason': 'No path found', 'partid': 790, 'amount_msat': 50476, 'parent_partid': 459}, {'status': 'failed', 'failreason': 'No path found', 'partid': 895, 'amount_msat': 50476, 'parent_partid': 790}, {'status': 'failed', 'failreason': 'No path found', 'partid': 460, 'amount_msat': 109255, 'parent_partid': 237}, {'status': 'pending', 'failreason': 'No path found', 'partid': 555, 'amount_msat': 109255, 'parent_partid': 460}, {'status': 'failed', 'failreason': 'No path found', 'partid': 962, 'amount_msat': 51120, 'parent_partid': 555}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1096, 'amount_msat': 51120, 'parent_partid': 962}, {'status': 'failed', 'failreason': 'No path found', 'partid': 963, 'amount_msat': 58135, 'parent_partid': 555}, {'status': 'failed', 'failreason': 'No path found', 'partid': 238, 'amount_msat': 214263, 'parent_partid': 113}, {'status': 'pending', 'failreason': 'No path found', 'partid': 301, 'amount_msat': 214263, 'parent_partid': 238}, {'status': 'pending', 'failreason': 'No path found', 'partid': 597, 'amount_msat': 114003, 'parent_partid': 301}, {'status': 'failed', 'failreason': 'No path found', 'partid': 998, 'amount_msat': 52058, 'parent_partid': 597}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1492, 'amount_msat': 52058, 'parent_partid': 998}, {'status': 'failed', 'failreason': 'No path found', 'partid': 999, 'amount_msat': 61945, 'parent_partid': 597}, {'status': 'failed', 'failreason': 'No path found', 'partid': 598, 'amount_msat': 100260, 'parent_partid': 301}, {'status': 'pending', 'failreason': 'No path found', 'partid': 1000, 'amount_msat': 100260, 'parent_partid': 598}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1493, 'amount_msat': 55119, 'parent_partid': 1000}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1494, 'amount_msat': 45141, 'parent_partid': 1000}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1596, 'amount_msat': 45141, 'parent_partid': 1494}, {'status': 'failed', 'failreason': 'No path found', 'partid': 114, 'amount_msat': 353555, 'parent_partid': 48}, {'status': 'pending', 'failreason': 'No path found', 'partid': 239, 'amount_msat': 353555, 'parent_partid': 114}, {'status': 'pending', 'failreason': 'No path found', 'partid': 461, 'amount_msat': 178217, 'parent_partid': 239}, {'status': 'failed', 'failreason': 'No path found', 'partid': 791, 'amount_msat': 90368, 'parent_partid': 461}, {'status': 'failed', 'failreason': 'No path found', 'partid': 792, 'amount_msat': 87849, 'parent_partid': 461}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1245, 'amount_msat': 87849, 'parent_partid': 792}, {'status': 'failed', 'failreason': 'No path found', 'partid': 462, 'amount_msat': 175338, 'parent_partid': 239}, {'status': 'pending', 'failreason': 'No path found', 'partid': 793, 'amount_msat': 175338, 'parent_partid': 462}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1246, 'amount_msat': 92469, 'parent_partid': 793}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1361, 'amount_msat': 92469, 'parent_partid': 1246}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1247, 'amount_msat': 82869, 'parent_partid': 793}, {'status': 'pending', 'failreason': 'No path found', 'partid': 35, 'amount_msat': 767757, 'parent_partid': 25}, {'status': 'pending', 'failreason': 'No path found', 'partid': 49, 'amount_msat': 409798, 'parent_partid': 35}, {'status': 'pending', 'failreason': 'No path found', 'partid': 115, 'amount_msat': 192473, 'parent_partid': 49}, {'status': 'failed', 'failreason': 'No path found', 'partid': 240, 'amount_msat': 93160, 'parent_partid': 115}, {'status': 'failed', 'failreason': 'No path found', 'partid': 463, 'amount_msat': 93160, 'parent_partid': 240}, {'status': 'failed', 'failreason': 'No path found', 'partid': 241, 'amount_msat': 99313, 'parent_partid': 115}, {'status': 'failed', 'failreason': 'No path found', 'partid': 116, 'amount_msat': 217325, 'parent_partid': 49}, {'status': 'pending', 'failreason': 'No path found', 'partid': 148, 'amount_msat': 217325, 'parent_partid': 116}, {'status': 'failed', 'failreason': 'No path found', 'partid': 194, 'amount_msat': 114399, 'parent_partid': 148}, {'status': 'pending', 'failreason': 'No path found', 'partid': 273, 'amount_msat': 114399, 'parent_partid': 194}, {'status': 'failed', 'failreason': 'No path found', 'partid': 572, 'amount_msat': 58291, 'parent_partid': 273}, {'status': 'failed', 'failreason': 'No path found', 'partid': 979, 'amount_msat': 58291, 'parent_partid': 572}, {'status': 'failed', 'failreason': 'No path found', 'partid': 573, 'amount_msat': 56108, 'parent_partid': 273}, {'status': 'pending', 'failreason': 'No path found', 'partid': 195, 'amount_msat': 102926, 'parent_partid': 148}, {'status': 'failed', 'failreason': 'No path found', 'partid': 274, 'amount_msat': 53898, 'parent_partid': 195}, {'status': 'failed', 'failreason': 'No path found', 'partid': 574, 'amount_msat': 53898, 'parent_partid': 274}, {'status': 'failed', 'failreason': 'No path found', 'partid': 275, 'amount_msat': 49028, 'parent_partid': 195}, {'status': 'failed', 'failreason': 'No path found', 'partid': 50, 'amount_msat': 357959, 'parent_partid': 35}, {'status': 'pending', 'failreason': 'No path found', 'partid': 64, 'amount_msat': 357959, 'parent_partid': 50}, {'status': 'failed', 'failreason': 'No path found', 'partid': 88, 'amount_msat': 166701, 'parent_partid': 64}, {'status': 'pending', 'failreason': 'No path found', 'partid': 215, 'amount_msat': 166701, 'parent_partid': 88}, {'status': 'failed', 'failreason': 'No path found', 'partid': 435, 'amount_msat': 77478, 'parent_partid': 215}, {'status': 'failed', 'failreason': 'No path found', 'partid': 436, 'amount_msat': 89223, 'parent_partid': 215}, {'status': 'failed', 'failreason': 'No path found', 'partid': 531, 'amount_msat': 89223, 'parent_partid': 436}, {'status': 'pending', 'failreason': 'No path found', 'partid': 89, 'amount_msat': 191258, 'parent_partid': 64}, {'status': 'failed', 'failreason': 'No path found', 'partid': 216, 'amount_msat': 101663, 'parent_partid': 89}, {'status': 'pending', 'failreason': 'No path found', 'partid': 291, 'amount_msat': 101663, 'parent_partid': 216}, {'status': 'failed', 'failreason': 'No path found', 'partid': 584, 'amount_msat': 47793, 'parent_partid': 291}, {'status': 'failed', 'failreason': 'No path found', 'partid': 686, 'amount_msat': 47793, 'parent_partid': 584}, {'status': 'failed', 'failreason': 'No path found', 'partid': 585, 'amount_msat': 53870, 'parent_partid': 291}, {'status': 'failed', 'failreason': 'No path found', 'partid': 217, 'amount_msat': 89595, 'parent_partid': 89}, {'status': 'failed', 'failreason': 'No path found', 'partid': 26, 'amount_msat': 1765177, 'parent_partid': 17}, {'status': 'pending', 'failreason': 'No path found', 'partid': 56, 'amount_msat': 1765177, 'parent_partid': 26}, {'status': 'failed', 'failreason': 'No path found', 'partid': 70, 'amount_msat': 873865, 'parent_partid': 56}, {'status': 'pending', 'failreason': 'No path found', 'partid': 95, 'amount_msat': 873865, 'parent_partid': 70}, {'status': 'pending', 'failreason': 'No path found', 'partid': 223, 'amount_msat': 440914, 'parent_partid': 95}, {'status': 'failed', 'failreason': 'No path found', 'partid': 442, 'amount_msat': 221670, 'parent_partid': 223}, {'status': 'pending', 'failreason': 'No path found', 'partid': 538, 'amount_msat': 221670, 'parent_partid': 442}, {'status': 'pending', 'failreason': 'No path found', 'partid': 943, 'amount_msat': 118881, 'parent_partid': 538}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1460, 'amount_msat': 56970, 'parent_partid': 943}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1896, 'amount_msat': 56970, 'parent_partid': 1460}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1461, 'amount_msat': 61911, 'parent_partid': 943}, {'status': 'failed', 'failreason': 'No path found', 'partid': 944, 'amount_msat': 102789, 'parent_partid': 538}, {'status': 'pending', 'failreason': 'No path found', 'partid': 1462, 'amount_msat': 102789, 'parent_partid': 944}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1582, 'amount_msat': 52463, 'parent_partid': 1462}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1977, 'amount_msat': 52463, 'parent_partid': 1582}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1583, 'amount_msat': 50326, 'parent_partid': 1462}, {'status': 'pending', 'failreason': 'No path found', 'partid': 443, 'amount_msat': 219244, 'parent_partid': 223}, {'status': 'pending', 'failreason': 'No path found', 'partid': 539, 'amount_msat': 113533, 'parent_partid': 443}, {'status': 'failed', 'failreason': 'No path found', 'partid': 945, 'amount_msat': 60354, 'parent_partid': 539}, {'status': 'failed', 'failreason': 'No path found', 'partid': 946, 'amount_msat': 53179, 'parent_partid': 539}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1083, 'amount_msat': 53179, 'parent_partid': 946}, {'status': 'failed', 'failreason': 'No path found', 'partid': 540, 'amount_msat': 105711, 'parent_partid': 443}, {'status': 'pending', 'failreason': 'No path found', 'partid': 947, 'amount_msat': 105711, 'parent_partid': 540}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1463, 'amount_msat': 48849, 'parent_partid': 947}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1464, 'amount_msat': 56862, 'parent_partid': 947}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1584, 'amount_msat': 56862, 'parent_partid': 1464}, {'status': 'failed', 'failreason': 'No path found', 'partid': 224, 'amount_msat': 432951, 'parent_partid': 95}, {'status': 'pending', 'failreason': 'No path found', 'partid': 444, 'amount_msat': 432951, 'parent_partid': 224}, {'status': 'pending', 'failreason': 'No path found', 'partid': 541, 'amount_msat': 197059, 'parent_partid': 444}, {'status': 'failed', 'failreason': 'No path found', 'partid': 948, 'amount_msat': 103372, 'parent_partid': 541}, {'status': 'pending', 'failreason': 'No path found', 'partid': 1465, 'amount_msat': 103372, 'parent_partid': 948}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1585, 'amount_msat': 49883, 'parent_partid': 1465}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1586, 'amount_msat': 53489, 'parent_partid': 1465}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1978, 'amount_msat': 53489, 'parent_partid': 1586}, {'status': 'failed', 'failreason': 'No path found', 'partid': 949, 'amount_msat': 93687, 'parent_partid': 541}, {'status': 'failed', 'failreason': 'No path found', 'partid': 542, 'amount_msat': 235892, 'parent_partid': 444}, {'status': 'pending', 'failreason': 'No path found', 'partid': 950, 'amount_msat': 235892, 'parent_partid': 542}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1084, 'amount_msat': 129612, 'parent_partid': 950}, {'status': 'pending', 'failreason': 'No path found', 'partid': 1644, 'amount_msat': 129612, 'parent_partid': 1084}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1997, 'amount_msat': 65593, 'parent_partid': 1644}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1998, 'amount_msat': 64019, 'parent_partid': 1644}, {'status': 'failed', 'failreason': 'No path found', 'partid': 2040, 'amount_msat': 64019, 'parent_partid': 1998}, {'status': 'pending', 'failreason': 'No path found', 'partid': 1085, 'amount_msat': 106280, 'parent_partid': 950}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1645, 'amount_msat': 50294, 'parent_partid': 1085}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1646, 'amount_msat': 55986, 'parent_partid': 1085}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1770, 'amount_msat': 55986, 'parent_partid': 1646}, {'status': 'pending', 'failreason': 'No path found', 'partid': 71, 'amount_msat': 891312, 'parent_partid': 56}, {'status': 'failed', 'failreason': 'No path found', 'partid': 162, 'amount_msat': 464517, 'parent_partid': 71}, {'status': 'pending', 'failreason': 'No path found', 'partid': 330, 'amount_msat': 464517, 'parent_partid': 162}, {'status': 'pending', 'failreason': 'No path found', 'partid': 617, 'amount_msat': 223241, 'parent_partid': 330}, {'status': 'failed', 'failreason': 'No path found', 'partid': 704, 'amount_msat': 110404, 'parent_partid': 617}, {'status': 'pending', 'failreason': 'No path found', 'partid': 850, 'amount_msat': 110404, 'parent_partid': 704}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1409, 'amount_msat': 60448, 'parent_partid': 850}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1410, 'amount_msat': 49956, 'parent_partid': 850}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1567, 'amount_msat': 49956, 'parent_partid': 1410}, {'status': 'pending', 'failreason': 'No path found', 'partid': 705, 'amount_msat': 112837, 'parent_partid': 617}, {'status': 'failed', 'failreason': 'No path found', 'partid': 851, 'amount_msat': 53657, 'parent_partid': 705}, {'status': 'failed', 'failreason': 'No path found', 'partid': 852, 'amount_msat': 59180, 'parent_partid': 705}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1039, 'amount_msat': 59180, 'parent_partid': 852}, {'status': 'failed', 'failreason': 'No path found', 'partid': 618, 'amount_msat': 241276, 'parent_partid': 330}, {'status': 'pending', 'failreason': 'No path found', 'partid': 1018, 'amount_msat': 241276, 'parent_partid': 618}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1508, 'amount_msat': 130997, 'parent_partid': 1018}, {'status': 'pending', 'failreason': 'No path found', 'partid': 1910, 'amount_msat': 130997, 'parent_partid': 1508}, {'status': 'failed', 'failreason': 'No path found', 'partid': 2097, 'amount_msat': 64559, 'parent_partid': 1910}, {'status': 'failed', 'failreason': 'No path found', 'partid': 2098, 'amount_msat': 66438, 'parent_partid': 1910}, {'status': 'failed', 'failreason': 'No path found', 'partid': 2165, 'amount_msat': 66438, 'parent_partid': 2098}, {'status': 'pending', 'failreason': 'No path found', 'partid': 1509, 'amount_msat': 110279, 'parent_partid': 1018}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1911, 'amount_msat': 50165, 'parent_partid': 1509}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1912, 'amount_msat': 60114, 'parent_partid': 1509}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1951, 'amount_msat': 60114, 'parent_partid': 1912}, {'status': 'pending', 'failreason': 'No path found', 'partid': 163, 'amount_msat': 426795, 'parent_partid': 71}, {'status': 'pending', 'failreason': 'No path found', 'partid': 331, 'amount_msat': 230367, 'parent_partid': 163}, {'status': 'failed', 'failreason': 'No path found', 'partid': 400, 'amount_msat': 107384, 'parent_partid': 331}, {'status': 'pending', 'failreason': 'No path found', 'partid': 746, 'amount_msat': 107384, 'parent_partid': 400}, {'status': 'failed', 'failreason': 'No path found', 'partid': 866, 'amount_msat': 52077, 'parent_partid': 746}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1047, 'amount_msat': 52077, 'parent_partid': 866}, {'status': 'failed', 'failreason': 'No path found', 'partid': 867, 'amount_msat': 55307, 'parent_partid': 746}, {'status': 'pending', 'failreason': 'No path found', 'partid': 401, 'amount_msat': 122983, 'parent_partid': 331}, {'status': 'failed', 'failreason': 'No path found', 'partid': 747, 'amount_msat': 59427, 'parent_partid': 401}, {'status': 'failed', 'failreason': 'No path found', 'partid': 748, 'amount_msat': 63556, 'parent_partid': 401}, {'status': 'failed', 'failreason': 'No path found', 'partid': 868, 'amount_msat': 63556, 'parent_partid': 748}, {'status': 'failed', 'failreason': 'No path found', 'partid': 332, 'amount_msat': 196428, 'parent_partid': 163}, {'status': 'pending', 'failreason': 'No path found', 'partid': 619, 'amount_msat': 196428, 'parent_partid': 332}, {'status': 'failed', 'failreason': 'No path found', 'partid': 706, 'amount_msat': 105412, 'parent_partid': 619}, {'status': 'pending', 'failreason': 'No path found', 'partid': 1182, 'amount_msat': 105412, 'parent_partid': 706}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1695, 'amount_msat': 49847, 'parent_partid': 1182}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1696, 'amount_msat': 55565, 'parent_partid': 1182}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1790, 'amount_msat': 55565, 'parent_partid': 1696}, {'status': 'failed', 'failreason': 'No path found', 'partid': 707, 'amount_msat': 91016, 'parent_partid': 619}, {'status': 'failed', 'failreason': 'No path found', 'partid': 10, 'amount_msat': 6036251, 'parent_partid': 8}, {'status': 'pending', 'failreason': 'No path found', 'partid': 18, 'amount_msat': 6036251, 'parent_partid': 10}, {'status': 'pending', 'failreason': 'No path found', 'partid': 27, 'amount_msat': 3240573, 'parent_partid': 18}, {'status': 'failed', 'failreason': 'No path found', 'partid': 36, 'amount_msat': 1685588, 'parent_partid': 27}, {'status': 'pending', 'failreason': 'No path found', 'partid': 74, 'amount_msat': 1685588, 'parent_partid': 36}, {'status': 'failed', 'failreason': 'No path found', 'partid': 98, 'amount_msat': 904573, 'parent_partid': 74}, {'status': 'pending', 'failreason': 'No path found', 'partid': 135, 'amount_msat': 904573, 'parent_partid': 98}, {'status': 'pending', 'failreason': 'No path found', 'partid': 317, 'amount_msat': 469844, 'parent_partid': 135}, {'status': 'failed', 'failreason': 'No path found', 'partid': 608, 'amount_msat': 215968, 'parent_partid': 317}, {'status': 'pending', 'failreason': 'No path found', 'partid': 695, 'amount_msat': 215968, 'parent_partid': 608}, {'status': 'pending', 'failreason': 'No path found', 'partid': 843, 'amount_msat': 107627, 'parent_partid': 695}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1404, 'amount_msat': 57598, 'parent_partid': 843}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1860, 'amount_msat': 57598, 'parent_partid': 1404}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1405, 'amount_msat': 50029, 'parent_partid': 843}, {'status': 'failed', 'failreason': 'No path found', 'partid': 844, 'amount_msat': 108341, 'parent_partid': 695}, {'status': 'pending', 'failreason': 'No path found', 'partid': 1037, 'amount_msat': 108341, 'parent_partid': 844}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1622, 'amount_msat': 59026, 'parent_partid': 1037}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1763, 'amount_msat': 59026, 'parent_partid': 1622}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1623, 'amount_msat': 49315, 'parent_partid': 1037}, {'status': 'pending', 'failreason': 'No path found', 'partid': 609, 'amount_msat': 253876, 'parent_partid': 317}, {'status': 'failed', 'failreason': 'No path found', 'partid': 696, 'amount_msat': 135754, 'parent_partid': 609}, {'status': 'pending', 'failreason': 'No path found', 'partid': 1176, 'amount_msat': 135754, 'parent_partid': 696}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1692, 'amount_msat': 70840, 'parent_partid': 1176}, {'status': 'failed', 'failreason': 'No path found', 'partid': 2011, 'amount_msat': 70840, 'parent_partid': 1692}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1693, 'amount_msat': 64914, 'parent_partid': 1176}, {'status': 'pending', 'failreason': 'No path found', 'partid': 697, 'amount_msat': 118122, 'parent_partid': 609}, {'status': 'failed', 'failreason': 'No path found', 'partid': 845, 'amount_msat': 60773, 'parent_partid': 697}, {'status': 'failed', 'failreason': 'No path found', 'partid': 846, 'amount_msat': 57349, 'parent_partid': 697}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1406, 'amount_msat': 57349, 'parent_partid': 846}, {'status': 'failed', 'failreason': 'No path found', 'partid': 318, 'amount_msat': 434729, 'parent_partid': 135}, {'status': 'pending', 'failreason': 'No path found', 'partid': 610, 'amount_msat': 434729, 'parent_partid': 318}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1012, 'amount_msat': 208702, 'parent_partid': 610}, {'status': 'pending', 'failreason': 'No path found', 'partid': 1501, 'amount_msat': 208702, 'parent_partid': 1012}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1603, 'amount_msat': 94568, 'parent_partid': 1501}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1604, 'amount_msat': 114134, 'parent_partid': 1501}, {'status': 'pending', 'failreason': 'No path found', 'partid': 1987, 'amount_msat': 114134, 'parent_partid': 1604}, {'status': 'failed', 'failreason': 'No path found', 'partid': 2133, 'amount_msat': 58368, 'parent_partid': 1987}, {'status': 'failed', 'failreason': 'No path found', 'partid': 2134, 'amount_msat': 55766, 'parent_partid': 1987}, {'status': 'failed', 'failreason': 'No path found', 'partid': 2150, 'amount_msat': 55766, 'parent_partid': 2134}, {'status': 'pending', 'failreason': 'No path found', 'partid': 1013, 'amount_msat': 226027, 'parent_partid': 610}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1502, 'amount_msat': 106473, 'parent_partid': 1013}, {'status': 'pending', 'failreason': 'No path found', 'partid': 1907, 'amount_msat': 106473, 'parent_partid': 1502}, {'status': 'failed', 'failreason': 'No path found', 'partid': 2093, 'amount_msat': 53984, 'parent_partid': 1907}, {'status': 'failed', 'failreason': 'No path found', 'partid': 2094, 'amount_msat': 52489, 'parent_partid': 1907}, {'status': 'failed', 'failreason': 'No path found', 'partid': 2111, 'amount_msat': 52489, 'parent_partid': 2094}, {'status': 'pending', 'failreason': 'No path found', 'partid': 1503, 'amount_msat': 119554, 'parent_partid': 1013}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1605, 'amount_msat': 62223, 'parent_partid': 1503}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1606, 'amount_msat': 57331, 'parent_partid': 1503}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1988, 'amount_msat': 57331, 'parent_partid': 1606}, {'status': 'pending', 'failreason': 'No path found', 'partid': 99, 'amount_msat': 781015, 'parent_partid': 74}, {'status': 'failed', 'failreason': 'No path found', 'partid': 226, 'amount_msat': 403362, 'parent_partid': 99}, {'status': 'pending', 'failreason': 'No path found', 'partid': 447, 'amount_msat': 403362, 'parent_partid': 226}, {'status': 'failed', 'failreason': 'No path found', 'partid': 544, 'amount_msat': 184791, 'parent_partid': 447}, {'status': 'pending', 'failreason': 'No path found', 'partid': 951, 'amount_msat': 184791, 'parent_partid': 544}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1086, 'amount_msat': 89920, 'parent_partid': 951}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1286, 'amount_msat': 89920, 'parent_partid': 1086}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1087, 'amount_msat': 94871, 'parent_partid': 951}, {'status': 'pending', 'failreason': 'No path found', 'partid': 545, 'amount_msat': 218571, 'parent_partid': 447}, {'status': 'failed', 'failreason': 'No path found', 'partid': 670, 'amount_msat': 100940, 'parent_partid': 545}, {'status': 'pending', 'failreason': 'No path found', 'partid': 825, 'amount_msat': 100940, 'parent_partid': 670}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1033, 'amount_msat': 50886, 'parent_partid': 825}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1034, 'amount_msat': 50054, 'parent_partid': 825}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1621, 'amount_msat': 50054, 'parent_partid': 1034}, {'status': 'pending', 'failreason': 'No path found', 'partid': 671, 'amount_msat': 117631, 'parent_partid': 545}, {'status': 'failed', 'failreason': 'No path found', 'partid': 826, 'amount_msat': 64649, 'parent_partid': 671}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1035, 'amount_msat': 64649, 'parent_partid': 826}, {'status': 'failed', 'failreason': 'No path found', 'partid': 827, 'amount_msat': 52982, 'parent_partid': 671}, {'status': 'pending', 'failreason': 'No path found', 'partid': 227, 'amount_msat': 377653, 'parent_partid': 99}, {'status': 'failed', 'failreason': 'No path found', 'partid': 448, 'amount_msat': 180338, 'parent_partid': 227}, {'status': 'pending', 'failreason': 'No path found', 'partid': 780, 'amount_msat': 180338, 'parent_partid': 448}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1238, 'amount_msat': 91635, 'parent_partid': 780}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1720, 'amount_msat': 91635, 'parent_partid': 1238}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1239, 'amount_msat': 88703, 'parent_partid': 780}, {'status': 'pending', 'failreason': 'No path found', 'partid': 449, 'amount_msat': 197315, 'parent_partid': 227}, {'status': 'failed', 'failreason': 'No path found', 'partid': 781, 'amount_msat': 92692, 'parent_partid': 449}, {'status': 'failed', 'failreason': 'No path found', 'partid': 782, 'amount_msat': 104623, 'parent_partid': 449}, {'status': 'pending', 'failreason': 'No path found', 'partid': 1240, 'amount_msat': 104623, 'parent_partid': 782}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1721, 'amount_msat': 57503, 'parent_partid': 1240}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1722, 'amount_msat': 47120, 'parent_partid': 1240}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1798, 'amount_msat': 47120, 'parent_partid': 1722}, {'status': 'pending', 'failreason': 'No path found', 'partid': 37, 'amount_msat': 1554985, 'parent_partid': 27}, {'status': 'pending', 'failreason': 'No path found', 'partid': 51, 'amount_msat': 850950, 'parent_partid': 37}, {'status': 'pending', 'failreason': 'No path found', 'partid': 117, 'amount_msat': 436364, 'parent_partid': 51}, {'status': 'pending', 'failreason': 'No path found', 'partid': 149, 'amount_msat': 215443, 'parent_partid': 117}, {'status': 'failed', 'failreason': 'No path found', 'partid': 196, 'amount_msat': 112203, 'parent_partid': 149}, {'status': 'pending', 'failreason': 'No path found', 'partid': 276, 'amount_msat': 112203, 'parent_partid': 196}, {'status': 'failed', 'failreason': 'No path found', 'partid': 356, 'amount_msat': 58871, 'parent_partid': 276}, {'status': 'failed', 'failreason': 'No path found', 'partid': 476, 'amount_msat': 58871, 'parent_partid': 356}, {'status': 'failed', 'failreason': 'No path found', 'partid': 357, 'amount_msat': 53332, 'parent_partid': 276}, {'status': 'pending', 'failreason': 'No path found', 'partid': 197, 'amount_msat': 103240, 'parent_partid': 149}, {'status': 'failed', 'failreason': 'No path found', 'partid': 277, 'amount_msat': 48304, 'parent_partid': 197}, {'status': 'failed', 'failreason': 'No path found', 'partid': 278, 'amount_msat': 54936, 'parent_partid': 197}, {'status': 'failed', 'failreason': 'No path found', 'partid': 575, 'amount_msat': 54936, 'parent_partid': 278}, {'status': 'failed', 'failreason': 'No path found', 'partid': 150, 'amount_msat': 220921, 'parent_partid': 117}, {'status': 'pending', 'failreason': 'No path found', 'partid': 198, 'amount_msat': 220921, 'parent_partid': 150}, {'status': 'pending', 'failreason': 'No path found', 'partid': 279, 'amount_msat': 113502, 'parent_partid': 198}, {'status': 'failed', 'failreason': 'No path found', 'partid': 358, 'amount_msat': 51732, 'parent_partid': 279}, {'status': 'failed', 'failreason': 'No path found', 'partid': 720, 'amount_msat': 51732, 'parent_partid': 358}, {'status': 'failed', 'failreason': 'No path found', 'partid': 359, 'amount_msat': 61770, 'parent_partid': 279}, {'status': 'failed', 'failreason': 'No path found', 'partid': 280, 'amount_msat': 107419, 'parent_partid': 198}, {'status': 'pending', 'failreason': 'No path found', 'partid': 360, 'amount_msat': 107419, 'parent_partid': 280}, {'status': 'failed', 'failreason': 'No path found', 'partid': 477, 'amount_msat': 51208, 'parent_partid': 360}, {'status': 'failed', 'failreason': 'No path found', 'partid': 478, 'amount_msat': 56211, 'parent_partid': 360}, {'status': 'failed', 'failreason': 'No path found', 'partid': 899, 'amount_msat': 56211, 'parent_partid': 478}, {'status': 'failed', 'failreason': 'No path found', 'partid': 118, 'amount_msat': 414586, 'parent_partid': 51}, {'status': 'pending', 'failreason': 'No path found', 'partid': 151, 'amount_msat': 414586, 'parent_partid': 118}, {'status': 'failed', 'failreason': 'No path found', 'partid': 322, 'amount_msat': 188623, 'parent_partid': 151}, {'status': 'pending', 'failreason': 'No path found', 'partid': 615, 'amount_msat': 188623, 'parent_partid': 322}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1014, 'amount_msat': 94024, 'parent_partid': 615}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1504, 'amount_msat': 94024, 'parent_partid': 1014}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1015, 'amount_msat': 94599, 'parent_partid': 615}, {'status': 'pending', 'failreason': 'No path found', 'partid': 323, 'amount_msat': 225963, 'parent_partid': 151}, {'status': 'pending', 'failreason': 'No path found', 'partid': 389, 'amount_msat': 120679, 'parent_partid': 323}, {'status': 'failed', 'failreason': 'No path found', 'partid': 740, 'amount_msat': 56457, 'parent_partid': 389}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1209, 'amount_msat': 56457, 'parent_partid': 740}, {'status': 'failed', 'failreason': 'No path found', 'partid': 741, 'amount_msat': 64222, 'parent_partid': 389}, {'status': 'failed', 'failreason': 'No path found', 'partid': 390, 'amount_msat': 105284, 'parent_partid': 323}, {'status': 'pending', 'failreason': 'No path found', 'partid': 742, 'amount_msat': 105284, 'parent_partid': 390}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1210, 'amount_msat': 54626, 'parent_partid': 742}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1339, 'amount_msat': 54626, 'parent_partid': 1210}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1211, 'amount_msat': 50658, 'parent_partid': 742}, {'status': 'failed', 'failreason': 'No path found', 'partid': 52, 'amount_msat': 704035, 'parent_partid': 37}, {'status': 'pending', 'failreason': 'No path found', 'partid': 119, 'amount_msat': 704035, 'parent_partid': 52}, {'status': 'failed', 'failreason': 'No path found', 'partid': 242, 'amount_msat': 358629, 'parent_partid': 119}, {'status': 'pending', 'failreason': 'No path found', 'partid': 302, 'amount_msat': 358629, 'parent_partid': 242}, {'status': 'pending', 'failreason': 'No path found', 'partid': 599, 'amount_msat': 190082, 'parent_partid': 302}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1001, 'amount_msat': 88792, 'parent_partid': 599}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1002, 'amount_msat': 101290, 'parent_partid': 599}, {'status': 'pending', 'failreason': 'No path found', 'partid': 1123, 'amount_msat': 101290, 'parent_partid': 1002}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1669, 'amount_msat': 48452, 'parent_partid': 1123}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1670, 'amount_msat': 52838, 'parent_partid': 1123}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1776, 'amount_msat': 52838, 'parent_partid': 1670}, {'status': 'failed', 'failreason': 'No path found', 'partid': 600, 'amount_msat': 168547, 'parent_partid': 302}, {'status': 'pending', 'failreason': 'No path found', 'partid': 692, 'amount_msat': 168547, 'parent_partid': 600}, {'status': 'failed', 'failreason': 'No path found', 'partid': 840, 'amount_msat': 83411, 'parent_partid': 692}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1403, 'amount_msat': 83411, 'parent_partid': 840}, {'status': 'failed', 'failreason': 'No path found', 'partid': 841, 'amount_msat': 85136, 'parent_partid': 692}, {'status': 'pending', 'failreason': 'No path found', 'partid': 243, 'amount_msat': 345406, 'parent_partid': 119}, {'status': 'pending', 'failreason': 'No path found', 'partid': 303, 'amount_msat': 184873, 'parent_partid': 243}, {'status': 'failed', 'failreason': 'No path found', 'partid': 372, 'amount_msat': 97191, 'parent_partid': 303}, {'status': 'failed', 'failreason': 'No path found', 'partid': 727, 'amount_msat': 97191, 'parent_partid': 372}, {'status': 'failed', 'failreason': 'No path found', 'partid': 373, 'amount_msat': 87682, 'parent_partid': 303}, {'status': 'failed', 'failreason': 'No path found', 'partid': 304, 'amount_msat': 160533, 'parent_partid': 243}, {'status': 'pending', 'failreason': 'No path found', 'partid': 374, 'amount_msat': 160533, 'parent_partid': 304}, {'status': 'failed', 'failreason': 'No path found', 'partid': 728, 'amount_msat': 86107, 'parent_partid': 374}, {'status': 'failed', 'failreason': 'No path found', 'partid': 859, 'amount_msat': 86107, 'parent_partid': 728}, {'status': 'failed', 'failreason': 'No path found', 'partid': 729, 'amount_msat': 74426, 'parent_partid': 374}, {'status': 'failed', 'failreason': 'No path found', 'partid': 28, 'amount_msat': 2795678, 'parent_partid': 18}, {'status': 'pending', 'failreason': 'No path found', 'partid': 57, 'amount_msat': 2795678, 'parent_partid': 28}, {'status': 'failed', 'failreason': 'No path found', 'partid': 120, 'amount_msat': 1345312, 'parent_partid': 57}, {'status': 'pending', 'failreason': 'No path found', 'partid': 152, 'amount_msat': 1345312, 'parent_partid': 120}, {'status': 'pending', 'failreason': 'No path found', 'partid': 199, 'amount_msat': 617735, 'parent_partid': 152}, {'status': 'failed', 'failreason': 'No path found', 'partid': 420, 'amount_msat': 328903, 'parent_partid': 199}, {'status': 'pending', 'failreason': 'No path found', 'partid': 755, 'amount_msat': 328903, 'parent_partid': 420}, {'status': 'failed', 'failreason': 'No path found', 'partid': 874, 'amount_msat': 178516, 'parent_partid': 755}, {'status': 'pending', 'failreason': 'No path found', 'partid': 1418, 'amount_msat': 178516, 'parent_partid': 874}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1862, 'amount_msat': 96384, 'parent_partid': 1418}, {'status': 'failed', 'failreason': 'No path found', 'partid': 2079, 'amount_msat': 96384, 'parent_partid': 1862}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1863, 'amount_msat': 82132, 'parent_partid': 1418}, {'status': 'pending', 'failreason': 'No path found', 'partid': 875, 'amount_msat': 150387, 'parent_partid': 755}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1419, 'amount_msat': 74394, 'parent_partid': 875}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1420, 'amount_msat': 75993, 'parent_partid': 875}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1573, 'amount_msat': 75993, 'parent_partid': 1420}, {'status': 'pending', 'failreason': 'No path found', 'partid': 421, 'amount_msat': 288832, 'parent_partid': 199}, {'status': 'failed', 'failreason': 'No path found', 'partid': 756, 'amount_msat': 147701, 'parent_partid': 421}, {'status': 'pending', 'failreason': 'No path found', 'partid': 876, 'amount_msat': 147701, 'parent_partid': 756}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1048, 'amount_msat': 78110, 'parent_partid': 876}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1265, 'amount_msat': 78110, 'parent_partid': 1048}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1049, 'amount_msat': 69591, 'parent_partid': 876}, {'status': 'pending', 'failreason': 'No path found', 'partid': 757, 'amount_msat': 141131, 'parent_partid': 421}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1218, 'amount_msat': 65463, 'parent_partid': 757}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1344, 'amount_msat': 65463, 'parent_partid': 1218}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1219, 'amount_msat': 75668, 'parent_partid': 757}, {'status': 'failed', 'failreason': 'No path found', 'partid': 200, 'amount_msat': 727577, 'parent_partid': 152}, {'status': 'pending', 'failreason': 'No path found', 'partid': 422, 'amount_msat': 727577, 'parent_partid': 200}, {'status': 'failed', 'failreason': 'No path found', 'partid': 758, 'amount_msat': 353265, 'parent_partid': 422}, {'status': 'pending', 'failreason': 'No path found', 'partid': 1220, 'amount_msat': 353265, 'parent_partid': 758}, {'status': 'pending', 'failreason': 'No path found', 'partid': 1345, 'amount_msat': 159804, 'parent_partid': 1220}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1835, 'amount_msat': 73352, 'parent_partid': 1345}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1836, 'amount_msat': 86452, 'parent_partid': 1345}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1937, 'amount_msat': 86452, 'parent_partid': 1836}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1346, 'amount_msat': 193461, 'parent_partid': 1220}, {'status': 'pending', 'failreason': 'No path found', 'partid': 1544, 'amount_msat': 193461, 'parent_partid': 1346}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1739, 'amount_msat': 89059, 'parent_partid': 1544}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1740, 'amount_msat': 104402, 'parent_partid': 1544}, {'status': 'pending', 'failreason': 'No path found', 'partid': 1920, 'amount_msat': 104402, 'parent_partid': 1740}, {'status': 'failed', 'failreason': 'No path found', 'partid': 2024, 'amount_msat': 51618, 'parent_partid': 1920}, {'status': 'failed', 'failreason': 'No path found', 'partid': 2145, 'amount_msat': 51618, 'parent_partid': 2024}, {'status': 'failed', 'failreason': 'No path found', 'partid': 2025, 'amount_msat': 52784, 'parent_partid': 1920}, {'status': 'pending', 'failreason': 'No path found', 'partid': 759, 'amount_msat': 374312, 'parent_partid': 422}, {'status': 'pending', 'failreason': 'No path found', 'partid': 1221, 'amount_msat': 183817, 'parent_partid': 759}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1347, 'amount_msat': 98061, 'parent_partid': 1221}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1348, 'amount_msat': 85756, 'parent_partid': 1221}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1545, 'amount_msat': 85756, 'parent_partid': 1348}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1222, 'amount_msat': 190495, 'parent_partid': 759}, {'status': 'pending', 'failreason': 'No path found', 'partid': 1710, 'amount_msat': 190495, 'parent_partid': 1222}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1793, 'amount_msat': 89608, 'parent_partid': 1710}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1794, 'amount_msat': 100887, 'parent_partid': 1710}, {'status': 'pending', 'failreason': 'No path found', 'partid': 2063, 'amount_msat': 100887, 'parent_partid': 1794}, {'status': 'failed', 'failreason': 'No path found', 'partid': 2159, 'amount_msat': 49890, 'parent_partid': 2063}, {'status': 'failed', 'failreason': 'No path found', 'partid': 2160, 'amount_msat': 50997, 'parent_partid': 2063}, {'status': 'failed', 'failreason': 'No path found', 'partid': 2180, 'amount_msat': 50997, 'parent_partid': 2160}, {'status': 'pending', 'failreason': 'No path found', 'partid': 121, 'amount_msat': 1450366, 'parent_partid': 57}, {'status': 'pending', 'failreason': 'No path found', 'partid': 153, 'amount_msat': 759550, 'parent_partid': 121}, {'status': 'pending', 'failreason': 'No path found', 'partid': 201, 'amount_msat': 352996, 'parent_partid': 153}, {'status': 'pending', 'failreason': 'No path found', 'partid': 281, 'amount_msat': 158994, 'parent_partid': 201}, {'status': 'failed', 'failreason': 'No path found', 'partid': 361, 'amount_msat': 77454, 'parent_partid': 281}, {'status': 'failed', 'failreason': 'No path found', 'partid': 362, 'amount_msat': 81540, 'parent_partid': 281}, {'status': 'failed', 'failreason': 'No path found', 'partid': 721, 'amount_msat': 81540, 'parent_partid': 362}, {'status': 'failed', 'failreason': 'No path found', 'partid': 282, 'amount_msat': 194002, 'parent_partid': 201}, {'status': 'pending', 'failreason': 'No path found', 'partid': 363, 'amount_msat': 194002, 'parent_partid': 282}, {'status': 'failed', 'failreason': 'No path found', 'partid': 479, 'amount_msat': 97166, 'parent_partid': 363}, {'status': 'failed', 'failreason': 'No path found', 'partid': 480, 'amount_msat': 96836, 'parent_partid': 363}, {'status': 'failed', 'failreason': 'No path found', 'partid': 900, 'amount_msat': 96836, 'parent_partid': 480}, {'status': 'failed', 'failreason': 'No path found', 'partid': 202, 'amount_msat': 406554, 'parent_partid': 153}, {'status': 'pending', 'failreason': 'No path found', 'partid': 283, 'amount_msat': 406554, 'parent_partid': 202}, {'status': 'failed', 'failreason': 'No path found', 'partid': 576, 'amount_msat': 184946, 'parent_partid': 283}, {'status': 'pending', 'failreason': 'No path found', 'partid': 980, 'amount_msat': 184946, 'parent_partid': 576}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1109, 'amount_msat': 90017, 'parent_partid': 980}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1110, 'amount_msat': 94929, 'parent_partid': 980}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1661, 'amount_msat': 94929, 'parent_partid': 1110}, {'status': 'pending', 'failreason': 'No path found', 'partid': 577, 'amount_msat': 221608, 'parent_partid': 283}, {'status': 'pending', 'failreason': 'No path found', 'partid': 981, 'amount_msat': 121873, 'parent_partid': 577}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1481, 'amount_msat': 65532, 'parent_partid': 981}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1482, 'amount_msat': 56341, 'parent_partid': 981}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1903, 'amount_msat': 56341, 'parent_partid': 1482}, {'status': 'failed', 'failreason': 'No path found', 'partid': 982, 'amount_msat': 99735, 'parent_partid': 577}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1111, 'amount_msat': 99735, 'parent_partid': 982}, {'status': 'failed', 'failreason': 'No path found', 'partid': 154, 'amount_msat': 690816, 'parent_partid': 121}, {'status': 'pending', 'failreason': 'No path found', 'partid': 324, 'amount_msat': 690816, 'parent_partid': 154}, {'status': 'pending', 'failreason': 'No path found', 'partid': 391, 'amount_msat': 334654, 'parent_partid': 324}, {'status': 'pending', 'failreason': 'No path found', 'partid': 497, 'amount_msat': 169158, 'parent_partid': 391}, {'status': 'failed', 'failreason': 'No path found', 'partid': 632, 'amount_msat': 86935, 'parent_partid': 497}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1141, 'amount_msat': 86935, 'parent_partid': 632}, {'status': 'failed', 'failreason': 'No path found', 'partid': 633, 'amount_msat': 82223, 'parent_partid': 497}, {'status': 'failed', 'failreason': 'No path found', 'partid': 498, 'amount_msat': 165496, 'parent_partid': 391}, {'status': 'pending', 'failreason': 'No path found', 'partid': 915, 'amount_msat': 165496, 'parent_partid': 498}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1068, 'amount_msat': 85637, 'parent_partid': 915}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1271, 'amount_msat': 85637, 'parent_partid': 1068}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1069, 'amount_msat': 79859, 'parent_partid': 915}, {'status': 'failed', 'failreason': 'No path found', 'partid': 392, 'amount_msat': 356162, 'parent_partid': 324}, {'status': 'pending', 'failreason': 'No path found', 'partid': 499, 'amount_msat': 356162, 'parent_partid': 392}, {'status': 'failed', 'failreason': 'No path found', 'partid': 916, 'amount_msat': 169615, 'parent_partid': 499}, {'status': 'pending', 'failreason': 'No path found', 'partid': 1436, 'amount_msat': 169615, 'parent_partid': 916}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1875, 'amount_msat': 86640, 'parent_partid': 1436}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1876, 'amount_msat': 82975, 'parent_partid': 1436}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1944, 'amount_msat': 82975, 'parent_partid': 1876}, {'status': 'pending', 'failreason': 'No path found', 'partid': 917, 'amount_msat': 186547, 'parent_partid': 499}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1437, 'amount_msat': 92228, 'parent_partid': 917}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1438, 'amount_msat': 94319, 'parent_partid': 917}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1877, 'amount_msat': 94319, 'parent_partid': 1438}, {'status': 'pending', 'failreason': 'No path found', 'partid': 5, 'amount_msat': 12608296, 'parent_partid': 3}, {'status': 'pending', 'failreason': 'No path found', 'partid': 11, 'amount_msat': 5967366, 'parent_partid': 5}, {'status': 'failed', 'failreason': 'No path found', 'partid': 32, 'amount_msat': 2862097, 'parent_partid': 11}, {'status': 'pending', 'failreason': 'No path found', 'partid': 61, 'amount_msat': 2862097, 'parent_partid': 32}, {'status': 'pending', 'failreason': 'No path found', 'partid': 125, 'amount_msat': 1406187, 'parent_partid': 61}, {'status': 'failed', 'failreason': 'No path found', 'partid': 246, 'amount_msat': 705481, 'parent_partid': 125}, {'status': 'pending', 'failreason': 'No path found', 'partid': 464, 'amount_msat': 705481, 'parent_partid': 246}, {'status': 'failed', 'failreason': 'No path found', 'partid': 794, 'amount_msat': 325513, 'parent_partid': 464}, {'status': 'pending', 'failreason': 'No path found', 'partid': 896, 'amount_msat': 325513, 'parent_partid': 794}, {'status': 'pending', 'failreason': 'No path found', 'partid': 1427, 'amount_msat': 151609, 'parent_partid': 896}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1867, 'amount_msat': 82500, 'parent_partid': 1427}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1868, 'amount_msat': 69109, 'parent_partid': 1427}, {'status': 'failed', 'failreason': 'No path found', 'partid': 2080, 'amount_msat': 69109, 'parent_partid': 1868}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1428, 'amount_msat': 173904, 'parent_partid': 896}, {'status': 'pending', 'failreason': 'No path found', 'partid': 1869, 'amount_msat': 173904, 'parent_partid': 1428}, {'status': 'failed', 'failreason': 'No path found', 'partid': 2081, 'amount_msat': 83451, 'parent_partid': 1869}, {'status': 'failed', 'failreason': 'No path found', 'partid': 2082, 'amount_msat': 90453, 'parent_partid': 1869}, {'status': 'failed', 'failreason': 'No path found', 'partid': 2108, 'amount_msat': 90453, 'parent_partid': 2082}, {'status': 'pending', 'failreason': 'No path found', 'partid': 795, 'amount_msat': 379968, 'parent_partid': 464}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1248, 'amount_msat': 192565, 'parent_partid': 795}, {'status': 'pending', 'failreason': 'No path found', 'partid': 1725, 'amount_msat': 192565, 'parent_partid': 1248}, {'status': 'pending', 'failreason': 'No path found', 'partid': 2019, 'amount_msat': 102893, 'parent_partid': 1725}, {'status': 'failed', 'failreason': 'No path found', 'partid': 2044, 'amount_msat': 47888, 'parent_partid': 2019}, {'status': 'failed', 'failreason': 'No path found', 'partid': 2154, 'amount_msat': 47888, 'parent_partid': 2044}, {'status': 'failed', 'failreason': 'No path found', 'partid': 2045, 'amount_msat': 55005, 'parent_partid': 2019}, {'status': 'failed', 'failreason': 'No path found', 'partid': 2020, 'amount_msat': 89672, 'parent_partid': 1725}, {'status': 'failed', 'failreason': 'No path found', 'partid': 2046, 'amount_msat': 89672, 'parent_partid': 2020}, {'status': 'pending', 'failreason': 'No path found', 'partid': 1249, 'amount_msat': 187403, 'parent_partid': 795}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1362, 'amount_msat': 86841, 'parent_partid': 1249}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1549, 'amount_msat': 86841, 'parent_partid': 1362}, {'status': 'pending', 'failreason': 'No path found', 'partid': 1363, 'amount_msat': 100562, 'parent_partid': 1249}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1550, 'amount_msat': 54272, 'parent_partid': 1363}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1961, 'amount_msat': 54272, 'parent_partid': 1550}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1551, 'amount_msat': 46290, 'parent_partid': 1363}, {'status': 'pending', 'failreason': 'No path found', 'partid': 247, 'amount_msat': 700706, 'parent_partid': 125}, {'status': 'failed', 'failreason': 'No path found', 'partid': 308, 'amount_msat': 376123, 'parent_partid': 247}, {'status': 'pending', 'failreason': 'No path found', 'partid': 603, 'amount_msat': 376123, 'parent_partid': 308}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1006, 'amount_msat': 184175, 'parent_partid': 603}, {'status': 'pending', 'failreason': 'No path found', 'partid': 1127, 'amount_msat': 184175, 'parent_partid': 1006}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1305, 'amount_msat': 99447, 'parent_partid': 1127}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1306, 'amount_msat': 84728, 'parent_partid': 1127}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1533, 'amount_msat': 84728, 'parent_partid': 1306}, {'status': 'pending', 'failreason': 'No path found', 'partid': 1007, 'amount_msat': 191948, 'parent_partid': 603}, {'status': 'pending', 'failreason': 'No path found', 'partid': 1497, 'amount_msat': 102014, 'parent_partid': 1007}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1600, 'amount_msat': 54112, 'parent_partid': 1497}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1751, 'amount_msat': 54112, 'parent_partid': 1600}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1601, 'amount_msat': 47902, 'parent_partid': 1497}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1498, 'amount_msat': 89934, 'parent_partid': 1007}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1602, 'amount_msat': 89934, 'parent_partid': 1498}, {'status': 'pending', 'failreason': 'No path found', 'partid': 309, 'amount_msat': 324583, 'parent_partid': 247}, {'status': 'failed', 'failreason': 'No path found', 'partid': 378, 'amount_msat': 175246, 'parent_partid': 309}, {'status': 'pending', 'failreason': 'No path found', 'partid': 731, 'amount_msat': 175246, 'parent_partid': 378}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1196, 'amount_msat': 84585, 'parent_partid': 731}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1702, 'amount_msat': 84585, 'parent_partid': 1196}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1197, 'amount_msat': 90661, 'parent_partid': 731}, {'status': 'pending', 'failreason': 'No path found', 'partid': 379, 'amount_msat': 149337, 'parent_partid': 309}, {'status': 'failed', 'failreason': 'No path found', 'partid': 492, 'amount_msat': 72840, 'parent_partid': 379}, {'status': 'failed', 'failreason': 'No path found', 'partid': 911, 'amount_msat': 72840, 'parent_partid': 492}, {'status': 'failed', 'failreason': 'No path found', 'partid': 493, 'amount_msat': 76497, 'parent_partid': 379}, {'status': 'failed', 'failreason': 'No path found', 'partid': 126, 'amount_msat': 1455910, 'parent_partid': 61}, {'status': 'pending', 'failreason': 'No path found', 'partid': 158, 'amount_msat': 1455910, 'parent_partid': 126}, {'status': 'pending', 'failreason': 'No path found', 'partid': 327, 'amount_msat': 661924, 'parent_partid': 158}, {'status': 'failed', 'failreason': 'No path found', 'partid': 396, 'amount_msat': 360013, 'parent_partid': 327}, {'status': 'pending', 'failreason': 'No path found', 'partid': 505, 'amount_msat': 360013, 'parent_partid': 396}, {'status': 'pending', 'failreason': 'No path found', 'partid': 637, 'amount_msat': 192359, 'parent_partid': 505}, {'status': 'failed', 'failreason': 'No path found', 'partid': 805, 'amount_msat': 95792, 'parent_partid': 637}, {'status': 'failed', 'failreason': 'No path found', 'partid': 806, 'amount_msat': 96567, 'parent_partid': 637}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1027, 'amount_msat': 96567, 'parent_partid': 806}, {'status': 'failed', 'failreason': 'No path found', 'partid': 638, 'amount_msat': 167654, 'parent_partid': 505}, {'status': 'pending', 'failreason': 'No path found', 'partid': 807, 'amount_msat': 167654, 'parent_partid': 638}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1376, 'amount_msat': 82674, 'parent_partid': 807}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1849, 'amount_msat': 82674, 'parent_partid': 1376}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1377, 'amount_msat': 84980, 'parent_partid': 807}, {'status': 'pending', 'failreason': 'No path found', 'partid': 397, 'amount_msat': 301911, 'parent_partid': 327}, {'status': 'pending', 'failreason': 'No path found', 'partid': 743, 'amount_msat': 149824, 'parent_partid': 397}, {'status': 'failed', 'failreason': 'No path found', 'partid': 862, 'amount_msat': 80195, 'parent_partid': 743}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1415, 'amount_msat': 80195, 'parent_partid': 862}, {'status': 'failed', 'failreason': 'No path found', 'partid': 863, 'amount_msat': 69629, 'parent_partid': 743}, {'status': 'failed', 'failreason': 'No path found', 'partid': 744, 'amount_msat': 152087, 'parent_partid': 397}, {'status': 'pending', 'failreason': 'No path found', 'partid': 1212, 'amount_msat': 152087, 'parent_partid': 744}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1706, 'amount_msat': 69605, 'parent_partid': 1212}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1792, 'amount_msat': 69605, 'parent_partid': 1706}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1707, 'amount_msat': 82482, 'parent_partid': 1212}, {'status': 'failed', 'failreason': 'No path found', 'partid': 328, 'amount_msat': 793986, 'parent_partid': 158}, {'status': 'pending', 'failreason': 'No path found', 'partid': 616, 'amount_msat': 793986, 'parent_partid': 328}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1016, 'amount_msat': 368179, 'parent_partid': 616}, {'status': 'pending', 'failreason': 'No path found', 'partid': 1505, 'amount_msat': 368179, 'parent_partid': 1016}, {'status': 'pending', 'failreason': 'No path found', 'partid': 1607, 'amount_msat': 181686, 'parent_partid': 1505}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1752, 'amount_msat': 97805, 'parent_partid': 1607}, {'status': 'failed', 'failreason': 'No path found', 'partid': 2053, 'amount_msat': 97805, 'parent_partid': 1752}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1753, 'amount_msat': 83881, 'parent_partid': 1607}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1608, 'amount_msat': 186493, 'parent_partid': 1505}, {'status': 'pending', 'failreason': 'No path found', 'partid': 1989, 'amount_msat': 186493, 'parent_partid': 1608}, {'status': 'pending', 'failreason': 'No path found', 'partid': 2135, 'amount_msat': 100519, 'parent_partid': 1989}, {'status': 'failed', 'failreason': 'No path found', 'partid': 2151, 'amount_msat': 49646, 'parent_partid': 2135}, {'status': 'failed', 'failreason': 'No path found', 'partid': 2152, 'amount_msat': 50873, 'parent_partid': 2135}, {'status': 'failed', 'failreason': 'No path found', 'partid': 2166, 'amount_msat': 50873, 'parent_partid': 2152}, {'status': 'failed', 'failreason': 'No path found', 'partid': 2136, 'amount_msat': 85974, 'parent_partid': 1989}, {'status': 'failed', 'failreason': 'No path found', 'partid': 2176, 'amount_msat': 85974, 'parent_partid': 2136}, {'status': 'pending', 'failreason': 'No path found', 'partid': 1017, 'amount_msat': 425807, 'parent_partid': 616}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1506, 'amount_msat': 219322, 'parent_partid': 1017}, {'status': 'pending', 'failreason': 'No path found', 'partid': 1609, 'amount_msat': 219322, 'parent_partid': 1506}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1754, 'amount_msat': 102219, 'parent_partid': 1609}, {'status': 'pending', 'failreason': 'No path found', 'partid': 1921, 'amount_msat': 102219, 'parent_partid': 1754}, {'status': 'failed', 'failreason': 'No path found', 'partid': 2115, 'amount_msat': 52513, 'parent_partid': 1921}, {'status': 'failed', 'failreason': 'No path found', 'partid': 2116, 'amount_msat': 49706, 'parent_partid': 1921}, {'status': 'failed', 'failreason': 'No path found', 'partid': 2147, 'amount_msat': 49706, 'parent_partid': 2116}, {'status': 'pending', 'failreason': 'No path found', 'partid': 1755, 'amount_msat': 117103, 'parent_partid': 1609}, {'status': 'failed', 'failreason': 'No path found', 'partid': 2054, 'amount_msat': 56110, 'parent_partid': 1755}, {'status': 'failed', 'failreason': 'No path found', 'partid': 2156, 'amount_msat': 56110, 'parent_partid': 2054}, {'status': 'failed', 'failreason': 'No path found', 'partid': 2055, 'amount_msat': 60993, 'parent_partid': 1755}, {'status': 'pending', 'failreason': 'No path found', 'partid': 1507, 'amount_msat': 206485, 'parent_partid': 1017}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1908, 'amount_msat': 101803, 'parent_partid': 1507}, {'status': 'pending', 'failreason': 'No path found', 'partid': 1950, 'amount_msat': 101803, 'parent_partid': 1908}, {'status': 'failed', 'failreason': 'No path found', 'partid': 2028, 'amount_msat': 46677, 'parent_partid': 1950}, {'status': 'failed', 'failreason': 'No path found', 'partid': 2101, 'amount_msat': 46677, 'parent_partid': 2028}, {'status': 'failed', 'failreason': 'No path found', 'partid': 2029, 'amount_msat': 55126, 'parent_partid': 1950}, {'status': 'pending', 'failreason': 'No path found', 'partid': 1909, 'amount_msat': 104682, 'parent_partid': 1507}, {'status': 'failed', 'failreason': 'No path found', 'partid': 2095, 'amount_msat': 56784, 'parent_partid': 1909}, {'status': 'failed', 'failreason': 'No path found', 'partid': 2096, 'amount_msat': 47898, 'parent_partid': 1909}, {'status': 'failed', 'failreason': 'No path found', 'partid': 2112, 'amount_msat': 47898, 'parent_partid': 2096}, {'status': 'pending', 'failreason': 'No path found', 'partid': 33, 'amount_msat': 3105269, 'parent_partid': 11}, {'status': 'failed', 'failreason': 'No path found', 'partid': 62, 'amount_msat': 1538301, 'parent_partid': 33}, {'status': 'pending', 'failreason': 'No path found', 'partid': 127, 'amount_msat': 1538301, 'parent_partid': 62}, {'status': 'failed', 'failreason': 'No path found', 'partid': 248, 'amount_msat': 806245, 'parent_partid': 127}, {'status': 'pending', 'failreason': 'No path found', 'partid': 465, 'amount_msat': 806245, 'parent_partid': 248}, {'status': 'failed', 'failreason': 'No path found', 'partid': 796, 'amount_msat': 421463, 'parent_partid': 465}, {'status': 'pending', 'failreason': 'No path found', 'partid': 1250, 'amount_msat': 421463, 'parent_partid': 796}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1364, 'amount_msat': 197377, 'parent_partid': 1250}, {'status': 'pending', 'failreason': 'No path found', 'partid': 1845, 'amount_msat': 197377, 'parent_partid': 1364}, {'status': 'failed', 'failreason': 'No path found', 'partid': 2074, 'amount_msat': 104228, 'parent_partid': 1845}, {'status': 'pending', 'failreason': 'No path found', 'partid': 2162, 'amount_msat': 104228, 'parent_partid': 2074}, {'status': 'failed', 'failreason': 'No path found', 'partid': 2169, 'amount_msat': 51965, 'parent_partid': 2162}, {'status': 'failed', 'failreason': 'No path found', 'partid': 2170, 'amount_msat': 52263, 'parent_partid': 2162}, {'status': 'failed', 'failreason': 'No path found', 'partid': 2178, 'amount_msat': 52263, 'parent_partid': 2170}, {'status': 'failed', 'failreason': 'No path found', 'partid': 2075, 'amount_msat': 93149, 'parent_partid': 1845}, {'status': 'pending', 'failreason': 'No path found', 'partid': 1365, 'amount_msat': 224086, 'parent_partid': 1250}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1552, 'amount_msat': 115764, 'parent_partid': 1365}, {'status': 'pending', 'failreason': 'No path found', 'partid': 1962, 'amount_msat': 115764, 'parent_partid': 1552}, {'status': 'failed', 'failreason': 'No path found', 'partid': 2122, 'amount_msat': 52298, 'parent_partid': 1962}, {'status': 'failed', 'failreason': 'No path found', 'partid': 2148, 'amount_msat': 52298, 'parent_partid': 2122}, {'status': 'failed', 'failreason': 'No path found', 'partid': 2123, 'amount_msat': 63466, 'parent_partid': 1962}, {'status': 'pending', 'failreason': 'No path found', 'partid': 1553, 'amount_msat': 108322, 'parent_partid': 1365}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1963, 'amount_msat': 53400, 'parent_partid': 1553}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1964, 'amount_msat': 54922, 'parent_partid': 1553}, {'status': 'failed', 'failreason': 'No path found', 'partid': 2031, 'amount_msat': 54922, 'parent_partid': 1964}, {'status': 'pending', 'failreason': 'No path found', 'partid': 797, 'amount_msat': 384782, 'parent_partid': 465}, {'status': 'pending', 'failreason': 'No path found', 'partid': 1251, 'amount_msat': 202279, 'parent_partid': 797}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1366, 'amount_msat': 93006, 'parent_partid': 1251}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1554, 'amount_msat': 93006, 'parent_partid': 1366}, {'status': 'pending', 'failreason': 'No path found', 'partid': 1367, 'amount_msat': 109273, 'parent_partid': 1251}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1846, 'amount_msat': 49690, 'parent_partid': 1367}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1938, 'amount_msat': 49690, 'parent_partid': 1846}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1847, 'amount_msat': 59583, 'parent_partid': 1367}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1252, 'amount_msat': 182503, 'parent_partid': 797}, {'status': 'pending', 'failreason': 'No path found', 'partid': 1726, 'amount_msat': 182503, 'parent_partid': 1252}, {'status': 'failed', 'failreason': 'No path found', 'partid': 2021, 'amount_msat': 85729, 'parent_partid': 1726}, {'status': 'failed', 'failreason': 'No path found', 'partid': 2022, 'amount_msat': 96774, 'parent_partid': 1726}, {'status': 'failed', 'failreason': 'No path found', 'partid': 2047, 'amount_msat': 96774, 'parent_partid': 2022}, {'status': 'pending', 'failreason': 'No path found', 'partid': 249, 'amount_msat': 732056, 'parent_partid': 127}, {'status': 'failed', 'failreason': 'No path found', 'partid': 310, 'amount_msat': 392827, 'parent_partid': 249}, {'status': 'pending', 'failreason': 'No path found', 'partid': 380, 'amount_msat': 392827, 'parent_partid': 310}, {'status': 'failed', 'failreason': 'No path found', 'partid': 732, 'amount_msat': 177644, 'parent_partid': 380}, {'status': 'pending', 'failreason': 'No path found', 'partid': 1198, 'amount_msat': 177644, 'parent_partid': 732}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1334, 'amount_msat': 89180, 'parent_partid': 1198}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1541, 'amount_msat': 89180, 'parent_partid': 1334}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1335, 'amount_msat': 88464, 'parent_partid': 1198}, {'status': 'pending', 'failreason': 'No path found', 'partid': 733, 'amount_msat': 215183, 'parent_partid': 380}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1199, 'amount_msat': 98359, 'parent_partid': 733}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1200, 'amount_msat': 116824, 'parent_partid': 733}, {'status': 'pending', 'failreason': 'No path found', 'partid': 1336, 'amount_msat': 116824, 'parent_partid': 1200}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1830, 'amount_msat': 59464, 'parent_partid': 1336}, {'status': 'failed', 'failreason': 'No path found', 'partid': 2069, 'amount_msat': 59464, 'parent_partid': 1830}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1831, 'amount_msat': 57360, 'parent_partid': 1336}, {'status': 'pending', 'failreason': 'No path found', 'partid': 311, 'amount_msat': 339229, 'parent_partid': 249}, {'status': 'failed', 'failreason': 'No path found', 'partid': 604, 'amount_msat': 166958, 'parent_partid': 311}, {'status': 'pending', 'failreason': 'No path found', 'partid': 1008, 'amount_msat': 166958, 'parent_partid': 604}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1499, 'amount_msat': 83095, 'parent_partid': 1008}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1500, 'amount_msat': 83863, 'parent_partid': 1008}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1906, 'amount_msat': 83863, 'parent_partid': 1500}, {'status': 'pending', 'failreason': 'No path found', 'partid': 605, 'amount_msat': 172271, 'parent_partid': 311}, {'status': 'failed', 'failreason': 'No path found', 'partid': 693, 'amount_msat': 89711, 'parent_partid': 605}, {'status': 'failed', 'failreason': 'No path found', 'partid': 694, 'amount_msat': 82560, 'parent_partid': 605}, {'status': 'failed', 'failreason': 'No path found', 'partid': 842, 'amount_msat': 82560, 'parent_partid': 694}, {'status': 'pending', 'failreason': 'No path found', 'partid': 63, 'amount_msat': 1566968, 'parent_partid': 33}, {'status': 'failed', 'failreason': 'No path found', 'partid': 128, 'amount_msat': 816993, 'parent_partid': 63}, {'status': 'pending', 'failreason': 'No path found', 'partid': 250, 'amount_msat': 816993, 'parent_partid': 128}, {'status': 'failed', 'failreason': 'No path found', 'partid': 312, 'amount_msat': 444458, 'parent_partid': 250}, {'status': 'pending', 'failreason': 'No path found', 'partid': 381, 'amount_msat': 444458, 'parent_partid': 312}, {'status': 'failed', 'failreason': 'No path found', 'partid': 494, 'amount_msat': 207501, 'parent_partid': 381}, {'status': 'pending', 'failreason': 'No path found', 'partid': 912, 'amount_msat': 207501, 'parent_partid': 494}, {'status': 'pending', 'failreason': 'No path found', 'partid': 1433, 'amount_msat': 102477, 'parent_partid': 912}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1870, 'amount_msat': 53854, 'parent_partid': 1433}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1941, 'amount_msat': 53854, 'parent_partid': 1870}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1871, 'amount_msat': 48623, 'parent_partid': 1433}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1434, 'amount_msat': 105024, 'parent_partid': 912}, {'status': 'pending', 'failreason': 'No path found', 'partid': 1872, 'amount_msat': 105024, 'parent_partid': 1434}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1942, 'amount_msat': 48341, 'parent_partid': 1872}, {'status': 'failed', 'failreason': 'No path found', 'partid': 2119, 'amount_msat': 48341, 'parent_partid': 1942}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1943, 'amount_msat': 56683, 'parent_partid': 1872}, {'status': 'pending', 'failreason': 'No path found', 'partid': 495, 'amount_msat': 236957, 'parent_partid': 381}, {'status': 'pending', 'failreason': 'No path found', 'partid': 913, 'amount_msat': 122890, 'parent_partid': 495}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1066, 'amount_msat': 55824, 'parent_partid': 913}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1270, 'amount_msat': 55824, 'parent_partid': 1066}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1067, 'amount_msat': 67066, 'parent_partid': 913}, {'status': 'failed', 'failreason': 'No path found', 'partid': 914, 'amount_msat': 114067, 'parent_partid': 495}, {'status': 'pending', 'failreason': 'No path found', 'partid': 1435, 'amount_msat': 114067, 'parent_partid': 914}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1873, 'amount_msat': 58662, 'parent_partid': 1435}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1874, 'amount_msat': 55405, 'parent_partid': 1435}, {'status': 'failed', 'failreason': 'No path found', 'partid': 2083, 'amount_msat': 55405, 'parent_partid': 1874}, {'status': 'pending', 'failreason': 'No path found', 'partid': 313, 'amount_msat': 372535, 'parent_partid': 250}, {'status': 'failed', 'failreason': 'No path found', 'partid': 606, 'amount_msat': 177978, 'parent_partid': 313}, {'status': 'pending', 'failreason': 'No path found', 'partid': 1009, 'amount_msat': 177978, 'parent_partid': 606}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1128, 'amount_msat': 84421, 'parent_partid': 1009}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1671, 'amount_msat': 84421, 'parent_partid': 1128}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1129, 'amount_msat': 93557, 'parent_partid': 1009}, {'status': 'pending', 'failreason': 'No path found', 'partid': 607, 'amount_msat': 194557, 'parent_partid': 313}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1010, 'amount_msat': 88229, 'parent_partid': 607}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1130, 'amount_msat': 88229, 'parent_partid': 1010}, {'status': 'pending', 'failreason': 'No path found', 'partid': 1011, 'amount_msat': 106328, 'parent_partid': 607}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1131, 'amount_msat': 50627, 'parent_partid': 1011}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1132, 'amount_msat': 55701, 'parent_partid': 1011}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1672, 'amount_msat': 55701, 'parent_partid': 1132}, {'status': 'pending', 'failreason': 'No path found', 'partid': 129, 'amount_msat': 749975, 'parent_partid': 63}, {'status': 'pending', 'failreason': 'No path found', 'partid': 251, 'amount_msat': 390742, 'parent_partid': 129}, {'status': 'failed', 'failreason': 'No path found', 'partid': 466, 'amount_msat': 197324, 'parent_partid': 251}, {'status': 'pending', 'failreason': 'No path found', 'partid': 556, 'amount_msat': 197324, 'parent_partid': 466}, {'status': 'failed', 'failreason': 'No path found', 'partid': 964, 'amount_msat': 92364, 'parent_partid': 556}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1471, 'amount_msat': 92364, 'parent_partid': 964}, {'status': 'pending', 'failreason': 'No path found', 'partid': 965, 'amount_msat': 104960, 'parent_partid': 556}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1472, 'amount_msat': 50679, 'parent_partid': 965}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1587, 'amount_msat': 50679, 'parent_partid': 1472}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1473, 'amount_msat': 54281, 'parent_partid': 965}, {'status': 'pending', 'failreason': 'No path found', 'partid': 467, 'amount_msat': 193418, 'parent_partid': 251}, {'status': 'failed', 'failreason': 'No path found', 'partid': 557, 'amount_msat': 88435, 'parent_partid': 467}, {'status': 'failed', 'failreason': 'No path found', 'partid': 558, 'amount_msat': 104983, 'parent_partid': 467}, {'status': 'pending', 'failreason': 'No path found', 'partid': 966, 'amount_msat': 104983, 'parent_partid': 558}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1474, 'amount_msat': 48670, 'parent_partid': 966}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1588, 'amount_msat': 48670, 'parent_partid': 1474}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1475, 'amount_msat': 56313, 'parent_partid': 966}, {'status': 'failed', 'failreason': 'No path found', 'partid': 252, 'amount_msat': 359233, 'parent_partid': 129}, {'status': 'pending', 'failreason': 'No path found', 'partid': 468, 'amount_msat': 359233, 'parent_partid': 252}, {'status': 'failed', 'failreason': 'No path found', 'partid': 798, 'amount_msat': 184907, 'parent_partid': 468}, {'status': 'pending', 'failreason': 'No path found', 'partid': 1253, 'amount_msat': 184907, 'parent_partid': 798}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1727, 'amount_msat': 87288, 'parent_partid': 1253}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1728, 'amount_msat': 97619, 'parent_partid': 1253}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1801, 'amount_msat': 97619, 'parent_partid': 1728}, {'status': 'pending', 'failreason': 'No path found', 'partid': 799, 'amount_msat': 174326, 'parent_partid': 468}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1254, 'amount_msat': 81794, 'parent_partid': 799}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1368, 'amount_msat': 81794, 'parent_partid': 1254}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1255, 'amount_msat': 92532, 'parent_partid': 799}, {'status': 'failed', 'failreason': 'No path found', 'partid': 12, 'amount_msat': 6640930, 'parent_partid': 5}, {'status': 'pending', 'failreason': 'No path found', 'partid': 19, 'amount_msat': 6640930, 'parent_partid': 12}, {'status': 'pending', 'failreason': 'No path found', 'partid': 41, 'amount_msat': 3513680, 'parent_partid': 19}, {'status': 'failed', 'failreason': 'No path found', 'partid': 80, 'amount_msat': 1768897, 'parent_partid': 41}, {'status': 'pending', 'failreason': 'No path found', 'partid': 169, 'amount_msat': 1768897, 'parent_partid': 80}, {'status': 'failed', 'failreason': 'No path found', 'partid': 338, 'amount_msat': 952500, 'parent_partid': 169}, {'status': 'pending', 'failreason': 'No path found', 'partid': 624, 'amount_msat': 952500, 'parent_partid': 338}, {'status': 'pending', 'failreason': 'No path found', 'partid': 711, 'amount_msat': 435774, 'parent_partid': 624}, {'status': 'failed', 'failreason': 'No path found', 'partid': 854, 'amount_msat': 217261, 'parent_partid': 711}, {'status': 'pending', 'failreason': 'No path found', 'partid': 1411, 'amount_msat': 217261, 'parent_partid': 854}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1568, 'amount_msat': 115335, 'parent_partid': 1411}, {'status': 'pending', 'failreason': 'No path found', 'partid': 1971, 'amount_msat': 115335, 'parent_partid': 1568}, {'status': 'failed', 'failreason': 'No path found', 'partid': 2035, 'amount_msat': 58201, 'parent_partid': 1971}, {'status': 'failed', 'failreason': 'No path found', 'partid': 2036, 'amount_msat': 57134, 'parent_partid': 1971}, {'status': 'failed', 'failreason': 'No path found', 'partid': 2103, 'amount_msat': 57134, 'parent_partid': 2036}, {'status': 'pending', 'failreason': 'No path found', 'partid': 1569, 'amount_msat': 101926, 'parent_partid': 1411}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1972, 'amount_msat': 46471, 'parent_partid': 1569}, {'status': 'failed', 'failreason': 'No path found', 'partid': 2125, 'amount_msat': 46471, 'parent_partid': 1972}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1973, 'amount_msat': 55455, 'parent_partid': 1569}, {'status': 'pending', 'failreason': 'No path found', 'partid': 855, 'amount_msat': 218513, 'parent_partid': 711}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1042, 'amount_msat': 115428, 'parent_partid': 855}, {'status': 'pending', 'failreason': 'No path found', 'partid': 1263, 'amount_msat': 115428, 'parent_partid': 1042}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1802, 'amount_msat': 56926, 'parent_partid': 1263}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1931, 'amount_msat': 56926, 'parent_partid': 1802}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1803, 'amount_msat': 58502, 'parent_partid': 1263}, {'status': 'pending', 'failreason': 'No path found', 'partid': 1043, 'amount_msat': 103085, 'parent_partid': 855}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1624, 'amount_msat': 53574, 'parent_partid': 1043}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1993, 'amount_msat': 53574, 'parent_partid': 1624}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1625, 'amount_msat': 49511, 'parent_partid': 1043}, {'status': 'failed', 'failreason': 'No path found', 'partid': 712, 'amount_msat': 516726, 'parent_partid': 624}, {'status': 'pending', 'failreason': 'No path found', 'partid': 1187, 'amount_msat': 516726, 'parent_partid': 712}, {'status': 'pending', 'failreason': 'No path found', 'partid': 1331, 'amount_msat': 266551, 'parent_partid': 1187}, {'status': 'pending', 'failreason': 'No path found', 'partid': 1539, 'amount_msat': 144175, 'parent_partid': 1331}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1735, 'amount_msat': 72598, 'parent_partid': 1539}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1736, 'amount_msat': 71577, 'parent_partid': 1539}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1919, 'amount_msat': 71577, 'parent_partid': 1736}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1540, 'amount_msat': 122376, 'parent_partid': 1331}, {'status': 'pending', 'failreason': 'No path found', 'partid': 1737, 'amount_msat': 122376, 'parent_partid': 1540}, {'status': 'failed', 'failreason': 'No path found', 'partid': 2049, 'amount_msat': 58436, 'parent_partid': 1737}, {'status': 'failed', 'failreason': 'No path found', 'partid': 2050, 'amount_msat': 63940, 'parent_partid': 1737}, {'status': 'failed', 'failreason': 'No path found', 'partid': 2155, 'amount_msat': 63940, 'parent_partid': 2050}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1332, 'amount_msat': 250175, 'parent_partid': 1187}, {'status': 'pending', 'failreason': 'No path found', 'partid': 1827, 'amount_msat': 250175, 'parent_partid': 1332}, {'status': 'pending', 'failreason': 'No path found', 'partid': 2067, 'amount_msat': 119084, 'parent_partid': 1827}, {'status': 'failed', 'failreason': 'No path found', 'partid': 2105, 'amount_msat': 54110, 'parent_partid': 2067}, {'status': 'failed', 'failreason': 'No path found', 'partid': 2106, 'amount_msat': 64974, 'parent_partid': 2067}, {'status': 'failed', 'failreason': 'No path found', 'partid': 2171, 'amount_msat': 64974, 'parent_partid': 2106}, {'status': 'failed', 'failreason': 'No path found', 'partid': 2068, 'amount_msat': 131091, 'parent_partid': 1827}, {'status': 'pending', 'failreason': 'No path found', 'partid': 2161, 'amount_msat': 131091, 'parent_partid': 2068}, {'status': 'failed', 'failreason': 'No path found', 'partid': 2167, 'amount_msat': 60102, 'parent_partid': 2161}, {'status': 'failed', 'failreason': 'No path found', 'partid': 2168, 'amount_msat': 70989, 'parent_partid': 2161}, {'status': 'failed', 'failreason': 'No path found', 'partid': 2181, 'amount_msat': 70989, 'parent_partid': 2168}, {'status': 'pending', 'failreason': 'No path found', 'partid': 339, 'amount_msat': 816397, 'parent_partid': 169}, {'status': 'failed', 'failreason': 'No path found', 'partid': 406, 'amount_msat': 387608, 'parent_partid': 339}, {'status': 'pending', 'failreason': 'No path found', 'partid': 751, 'amount_msat': 387608, 'parent_partid': 406}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1216, 'amount_msat': 211284, 'parent_partid': 751}, {'status': 'pending', 'failreason': 'No path found', 'partid': 1343, 'amount_msat': 211284, 'parent_partid': 1216}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1542, 'amount_msat': 95849, 'parent_partid': 1343}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1738, 'amount_msat': 95849, 'parent_partid': 1542}, {'status': 'pending', 'failreason': 'No path found', 'partid': 1543, 'amount_msat': 115435, 'parent_partid': 1343}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1957, 'amount_msat': 59028, 'parent_partid': 1543}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1958, 'amount_msat': 56407, 'parent_partid': 1543}, {'status': 'failed', 'failreason': 'No path found', 'partid': 2030, 'amount_msat': 56407, 'parent_partid': 1958}, {'status': 'pending', 'failreason': 'No path found', 'partid': 1217, 'amount_msat': 176324, 'parent_partid': 751}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1708, 'amount_msat': 87772, 'parent_partid': 1217}, {'status': 'failed', 'failreason': 'No path found', 'partid': 2015, 'amount_msat': 87772, 'parent_partid': 1708}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1709, 'amount_msat': 88552, 'parent_partid': 1217}, {'status': 'pending', 'failreason': 'No path found', 'partid': 407, 'amount_msat': 428789, 'parent_partid': 339}, {'status': 'failed', 'failreason': 'No path found', 'partid': 512, 'amount_msat': 218088, 'parent_partid': 407}, {'status': 'pending', 'failreason': 'No path found', 'partid': 926, 'amount_msat': 218088, 'parent_partid': 512}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1076, 'amount_msat': 110311, 'parent_partid': 926}, {'status': 'pending', 'failreason': 'No path found', 'partid': 1279, 'amount_msat': 110311, 'parent_partid': 1076}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1522, 'amount_msat': 58894, 'parent_partid': 1279}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1954, 'amount_msat': 58894, 'parent_partid': 1522}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1523, 'amount_msat': 51417, 'parent_partid': 1279}, {'status': 'pending', 'failreason': 'No path found', 'partid': 1077, 'amount_msat': 107777, 'parent_partid': 926}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1280, 'amount_msat': 55839, 'parent_partid': 1077}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1805, 'amount_msat': 55839, 'parent_partid': 1280}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1281, 'amount_msat': 51938, 'parent_partid': 1077}, {'status': 'pending', 'failreason': 'No path found', 'partid': 513, 'amount_msat': 210701, 'parent_partid': 407}, {'status': 'pending', 'failreason': 'No path found', 'partid': 927, 'amount_msat': 103406, 'parent_partid': 513}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1446, 'amount_msat': 54827, 'parent_partid': 927}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1884, 'amount_msat': 54827, 'parent_partid': 1446}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1447, 'amount_msat': 48579, 'parent_partid': 927}, {'status': 'failed', 'failreason': 'No path found', 'partid': 928, 'amount_msat': 107295, 'parent_partid': 513}, {'status': 'pending', 'failreason': 'No path found', 'partid': 1078, 'amount_msat': 107295, 'parent_partid': 928}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1282, 'amount_msat': 54715, 'parent_partid': 1078}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1524, 'amount_msat': 54715, 'parent_partid': 1282}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1283, 'amount_msat': 52580, 'parent_partid': 1078}, {'status': 'pending', 'failreason': 'No path found', 'partid': 81, 'amount_msat': 1744783, 'parent_partid': 41}, {'status': 'failed', 'failreason': 'No path found', 'partid': 104, 'amount_msat': 917461, 'parent_partid': 81}, {'status': 'pending', 'failreason': 'No path found', 'partid': 138, 'amount_msat': 917461, 'parent_partid': 104}, {'status': 'pending', 'failreason': 'No path found', 'partid': 181, 'amount_msat': 492605, 'parent_partid': 138}, {'status': 'pending', 'failreason': 'No path found', 'partid': 259, 'amount_msat': 260057, 'parent_partid': 181}, {'status': 'pending', 'failreason': 'No path found', 'partid': 561, 'amount_msat': 141958, 'parent_partid': 259}, {'status': 'failed', 'failreason': 'No path found', 'partid': 967, 'amount_msat': 66111, 'parent_partid': 561}, {'status': 'failed', 'failreason': 'No path found', 'partid': 968, 'amount_msat': 75847, 'parent_partid': 561}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1097, 'amount_msat': 75847, 'parent_partid': 968}, {'status': 'failed', 'failreason': 'No path found', 'partid': 562, 'amount_msat': 118099, 'parent_partid': 259}, {'status': 'pending', 'failreason': 'No path found', 'partid': 969, 'amount_msat': 118099, 'parent_partid': 562}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1098, 'amount_msat': 63110, 'parent_partid': 969}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1651, 'amount_msat': 63110, 'parent_partid': 1098}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1099, 'amount_msat': 54989, 'parent_partid': 969}, {'status': 'failed', 'failreason': 'No path found', 'partid': 260, 'amount_msat': 232548, 'parent_partid': 181}, {'status': 'pending', 'failreason': 'No path found', 'partid': 563, 'amount_msat': 232548, 'parent_partid': 260}, {'status': 'failed', 'failreason': 'No path found', 'partid': 970, 'amount_msat': 105210, 'parent_partid': 563}, {'status': 'pending', 'failreason': 'No path found', 'partid': 1476, 'amount_msat': 105210, 'parent_partid': 970}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1901, 'amount_msat': 53656, 'parent_partid': 1476}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1902, 'amount_msat': 51554, 'parent_partid': 1476}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1949, 'amount_msat': 51554, 'parent_partid': 1902}, {'status': 'pending', 'failreason': 'No path found', 'partid': 971, 'amount_msat': 127338, 'parent_partid': 563}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1100, 'amount_msat': 57916, 'parent_partid': 971}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1652, 'amount_msat': 57916, 'parent_partid': 1100}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1101, 'amount_msat': 69422, 'parent_partid': 971}, {'status': 'failed', 'failreason': 'No path found', 'partid': 182, 'amount_msat': 424856, 'parent_partid': 138}, {'status': 'pending', 'failreason': 'No path found', 'partid': 261, 'amount_msat': 424856, 'parent_partid': 182}, {'status': 'failed', 'failreason': 'No path found', 'partid': 564, 'amount_msat': 208154, 'parent_partid': 261}, {'status': 'pending', 'failreason': 'No path found', 'partid': 676, 'amount_msat': 208154, 'parent_partid': 564}, {'status': 'pending', 'failreason': 'No path found', 'partid': 1169, 'amount_msat': 104620, 'parent_partid': 676}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1325, 'amount_msat': 48395, 'parent_partid': 1169}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1326, 'amount_msat': 56225, 'parent_partid': 1169}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1826, 'amount_msat': 56225, 'parent_partid': 1326}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1170, 'amount_msat': 103534, 'parent_partid': 676}, {'status': 'pending', 'failreason': 'No path found', 'partid': 1327, 'amount_msat': 103534, 'parent_partid': 1170}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1537, 'amount_msat': 50418, 'parent_partid': 1327}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1538, 'amount_msat': 53116, 'parent_partid': 1327}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1956, 'amount_msat': 53116, 'parent_partid': 1538}, {'status': 'pending', 'failreason': 'No path found', 'partid': 565, 'amount_msat': 216702, 'parent_partid': 261}, {'status': 'failed', 'failreason': 'No path found', 'partid': 972, 'amount_msat': 105749, 'parent_partid': 565}, {'status': 'pending', 'failreason': 'No path found', 'partid': 1102, 'amount_msat': 105749, 'parent_partid': 972}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1653, 'amount_msat': 54947, 'parent_partid': 1102}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1654, 'amount_msat': 50802, 'parent_partid': 1102}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1771, 'amount_msat': 50802, 'parent_partid': 1654}, {'status': 'pending', 'failreason': 'No path found', 'partid': 973, 'amount_msat': 110953, 'parent_partid': 565}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1477, 'amount_msat': 52094, 'parent_partid': 973}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1478, 'amount_msat': 58859, 'parent_partid': 973}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1589, 'amount_msat': 58859, 'parent_partid': 1478}, {'status': 'pending', 'failreason': 'No path found', 'partid': 105, 'amount_msat': 827322, 'parent_partid': 81}, {'status': 'pending', 'failreason': 'No path found', 'partid': 139, 'amount_msat': 384757, 'parent_partid': 105}, {'status': 'pending', 'failreason': 'No path found', 'partid': 183, 'amount_msat': 201430, 'parent_partid': 139}, {'status': 'failed', 'failreason': 'No path found', 'partid': 414, 'amount_msat': 108113, 'parent_partid': 183}, {'status': 'pending', 'failreason': 'No path found', 'partid': 752, 'amount_msat': 108113, 'parent_partid': 414}, {'status': 'failed', 'failreason': 'No path found', 'partid': 869, 'amount_msat': 52126, 'parent_partid': 752}, {'status': 'failed', 'failreason': 'No path found', 'partid': 870, 'amount_msat': 55987, 'parent_partid': 752}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1416, 'amount_msat': 55987, 'parent_partid': 870}, {'status': 'failed', 'failreason': 'No path found', 'partid': 415, 'amount_msat': 93317, 'parent_partid': 183}, {'status': 'failed', 'failreason': 'No path found', 'partid': 184, 'amount_msat': 183327, 'parent_partid': 139}, {'status': 'pending', 'failreason': 'No path found', 'partid': 416, 'amount_msat': 183327, 'parent_partid': 184}, {'status': 'pending', 'failreason': 'No path found', 'partid': 753, 'amount_msat': 100477, 'parent_partid': 416}, {'status': 'failed', 'failreason': 'No path found', 'partid': 871, 'amount_msat': 52565, 'parent_partid': 753}, {'status': 'failed', 'failreason': 'No path found', 'partid': 872, 'amount_msat': 47912, 'parent_partid': 753}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1417, 'amount_msat': 47912, 'parent_partid': 872}, {'status': 'failed', 'failreason': 'No path found', 'partid': 754, 'amount_msat': 82850, 'parent_partid': 416}, {'status': 'failed', 'failreason': 'No path found', 'partid': 873, 'amount_msat': 82850, 'parent_partid': 754}, {'status': 'failed', 'failreason': 'No path found', 'partid': 140, 'amount_msat': 442565, 'parent_partid': 105}, {'status': 'pending', 'failreason': 'No path found', 'partid': 319, 'amount_msat': 442565, 'parent_partid': 140}, {'status': 'pending', 'failreason': 'No path found', 'partid': 387, 'amount_msat': 212916, 'parent_partid': 319}, {'status': 'pending', 'failreason': 'No path found', 'partid': 737, 'amount_msat': 116925, 'parent_partid': 387}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1204, 'amount_msat': 61491, 'parent_partid': 737}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1337, 'amount_msat': 61491, 'parent_partid': 1204}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1205, 'amount_msat': 55434, 'parent_partid': 737}, {'status': 'failed', 'failreason': 'No path found', 'partid': 738, 'amount_msat': 95991, 'parent_partid': 387}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1206, 'amount_msat': 95991, 'parent_partid': 738}, {'status': 'failed', 'failreason': 'No path found', 'partid': 388, 'amount_msat': 229649, 'parent_partid': 319}, {'status': 'pending', 'failreason': 'No path found', 'partid': 739, 'amount_msat': 229649, 'parent_partid': 388}, {'status': 'pending', 'failreason': 'No path found', 'partid': 1207, 'amount_msat': 106491, 'parent_partid': 739}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1704, 'amount_msat': 56351, 'parent_partid': 1207}, {'status': 'failed', 'failreason': 'No path found', 'partid': 2014, 'amount_msat': 56351, 'parent_partid': 1704}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1705, 'amount_msat': 50140, 'parent_partid': 1207}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1208, 'amount_msat': 123158, 'parent_partid': 739}, {'status': 'pending', 'failreason': 'No path found', 'partid': 1338, 'amount_msat': 123158, 'parent_partid': 1208}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1832, 'amount_msat': 59687, 'parent_partid': 1338}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1936, 'amount_msat': 59687, 'parent_partid': 1832}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1833, 'amount_msat': 63471, 'parent_partid': 1338}, {'status': 'failed', 'failreason': 'No path found', 'partid': 42, 'amount_msat': 3127250, 'parent_partid': 19}, {'status': 'pending', 'failreason': 'No path found', 'partid': 53, 'amount_msat': 3127250, 'parent_partid': 42}, {'status': 'pending', 'failreason': 'No path found', 'partid': 65, 'amount_msat': 1473763, 'parent_partid': 53}, {'status': 'failed', 'failreason': 'No path found', 'partid': 90, 'amount_msat': 763842, 'parent_partid': 65}, {'status': 'pending', 'failreason': 'No path found', 'partid': 218, 'amount_msat': 763842, 'parent_partid': 90}, {'status': 'failed', 'failreason': 'No path found', 'partid': 292, 'amount_msat': 354170, 'parent_partid': 218}, {'status': 'pending', 'failreason': 'No path found', 'partid': 369, 'amount_msat': 354170, 'parent_partid': 292}, {'status': 'failed', 'failreason': 'No path found', 'partid': 482, 'amount_msat': 194645, 'parent_partid': 369}, {'status': 'pending', 'failreason': 'No path found', 'partid': 629, 'amount_msat': 194645, 'parent_partid': 482}, {'status': 'failed', 'failreason': 'No path found', 'partid': 800, 'amount_msat': 104503, 'parent_partid': 629}, {'status': 'pending', 'failreason': 'No path found', 'partid': 1256, 'amount_msat': 104503, 'parent_partid': 800}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1369, 'amount_msat': 47061, 'parent_partid': 1256}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1370, 'amount_msat': 57442, 'parent_partid': 1256}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1555, 'amount_msat': 57442, 'parent_partid': 1370}, {'status': 'failed', 'failreason': 'No path found', 'partid': 801, 'amount_msat': 90142, 'parent_partid': 629}, {'status': 'pending', 'failreason': 'No path found', 'partid': 483, 'amount_msat': 159525, 'parent_partid': 369}, {'status': 'failed', 'failreason': 'No path found', 'partid': 903, 'amount_msat': 82720, 'parent_partid': 483}, {'status': 'failed', 'failreason': 'No path found', 'partid': 904, 'amount_msat': 76805, 'parent_partid': 483}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1430, 'amount_msat': 76805, 'parent_partid': 904}, {'status': 'pending', 'failreason': 'No path found', 'partid': 293, 'amount_msat': 409672, 'parent_partid': 218}, {'status': 'failed', 'failreason': 'No path found', 'partid': 586, 'amount_msat': 191699, 'parent_partid': 293}, {'status': 'pending', 'failreason': 'No path found', 'partid': 687, 'amount_msat': 191699, 'parent_partid': 586}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1172, 'amount_msat': 93950, 'parent_partid': 687}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1691, 'amount_msat': 93950, 'parent_partid': 1172}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1173, 'amount_msat': 97749, 'parent_partid': 687}, {'status': 'pending', 'failreason': 'No path found', 'partid': 587, 'amount_msat': 217973, 'parent_partid': 293}, {'status': 'failed', 'failreason': 'No path found', 'partid': 986, 'amount_msat': 100627, 'parent_partid': 587}, {'status': 'pending', 'failreason': 'No path found', 'partid': 1114, 'amount_msat': 100627, 'parent_partid': 986}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1293, 'amount_msat': 52655, 'parent_partid': 1114}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1294, 'amount_msat': 47972, 'parent_partid': 1114}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1526, 'amount_msat': 47972, 'parent_partid': 1294}, {'status': 'pending', 'failreason': 'No path found', 'partid': 987, 'amount_msat': 117346, 'parent_partid': 587}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1484, 'amount_msat': 60067, 'parent_partid': 987}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1904, 'amount_msat': 60067, 'parent_partid': 1484}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1485, 'amount_msat': 57279, 'parent_partid': 987}, {'status': 'pending', 'failreason': 'No path found', 'partid': 91, 'amount_msat': 709921, 'parent_partid': 65}, {'status': 'pending', 'failreason': 'No path found', 'partid': 219, 'amount_msat': 381818, 'parent_partid': 91}, {'status': 'pending', 'failreason': 'No path found', 'partid': 437, 'amount_msat': 191083, 'parent_partid': 219}, {'status': 'failed', 'failreason': 'No path found', 'partid': 776, 'amount_msat': 99992, 'parent_partid': 437}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1235, 'amount_msat': 99992, 'parent_partid': 776}, {'status': 'failed', 'failreason': 'No path found', 'partid': 777, 'amount_msat': 91091, 'parent_partid': 437}, {'status': 'failed', 'failreason': 'No path found', 'partid': 438, 'amount_msat': 190735, 'parent_partid': 219}, {'status': 'pending', 'failreason': 'No path found', 'partid': 532, 'amount_msat': 190735, 'parent_partid': 438}, {'status': 'failed', 'failreason': 'No path found', 'partid': 937, 'amount_msat': 88321, 'parent_partid': 532}, {'status': 'failed', 'failreason': 'No path found', 'partid': 938, 'amount_msat': 102414, 'parent_partid': 532}, {'status': 'pending', 'failreason': 'No path found', 'partid': 1456, 'amount_msat': 102414, 'parent_partid': 938}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1893, 'amount_msat': 46966, 'parent_partid': 1456}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1894, 'amount_msat': 55448, 'parent_partid': 1456}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1947, 'amount_msat': 55448, 'parent_partid': 1894}, {'status': 'failed', 'failreason': 'No path found', 'partid': 220, 'amount_msat': 328103, 'parent_partid': 91}, {'status': 'pending', 'failreason': 'No path found', 'partid': 439, 'amount_msat': 328103, 'parent_partid': 220}, {'status': 'pending', 'failreason': 'No path found', 'partid': 533, 'amount_msat': 167090, 'parent_partid': 439}, {'status': 'failed', 'failreason': 'No path found', 'partid': 939, 'amount_msat': 78133, 'parent_partid': 533}, {'status': 'failed', 'failreason': 'No path found', 'partid': 940, 'amount_msat': 88957, 'parent_partid': 533}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1457, 'amount_msat': 88957, 'parent_partid': 940}, {'status': 'failed', 'failreason': 'No path found', 'partid': 534, 'amount_msat': 161013, 'parent_partid': 439}, {'status': 'pending', 'failreason': 'No path found', 'partid': 664, 'amount_msat': 161013, 'parent_partid': 534}, {'status': 'failed', 'failreason': 'No path found', 'partid': 818, 'amount_msat': 78528, 'parent_partid': 664}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1385, 'amount_msat': 78528, 'parent_partid': 818}, {'status': 'failed', 'failreason': 'No path found', 'partid': 819, 'amount_msat': 82485, 'parent_partid': 664}, {'status': 'failed', 'failreason': 'No path found', 'partid': 66, 'amount_msat': 1653487, 'parent_partid': 53}, {'status': 'pending', 'failreason': 'No path found', 'partid': 92, 'amount_msat': 1653487, 'parent_partid': 66}, {'status': 'pending', 'failreason': 'No path found', 'partid': 221, 'amount_msat': 869622, 'parent_partid': 92}, {'status': 'failed', 'failreason': 'No path found', 'partid': 440, 'amount_msat': 407966, 'parent_partid': 221}, {'status': 'pending', 'failreason': 'No path found', 'partid': 535, 'amount_msat': 407966, 'parent_partid': 440}, {'status': 'pending', 'failreason': 'No path found', 'partid': 665, 'amount_msat': 217493, 'parent_partid': 535}, {'status': 'failed', 'failreason': 'No path found', 'partid': 820, 'amount_msat': 107211, 'parent_partid': 665}, {'status': 'pending', 'failreason': 'No path found', 'partid': 1386, 'amount_msat': 107211, 'parent_partid': 820}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1564, 'amount_msat': 55075, 'parent_partid': 1386}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1970, 'amount_msat': 55075, 'parent_partid': 1564}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1565, 'amount_msat': 52136, 'parent_partid': 1386}, {'status': 'pending', 'failreason': 'No path found', 'partid': 821, 'amount_msat': 110282, 'parent_partid': 665}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1387, 'amount_msat': 58562, 'parent_partid': 821}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1388, 'amount_msat': 51720, 'parent_partid': 821}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1851, 'amount_msat': 51720, 'parent_partid': 1388}, {'status': 'failed', 'failreason': 'No path found', 'partid': 666, 'amount_msat': 190473, 'parent_partid': 535}, {'status': 'pending', 'failreason': 'No path found', 'partid': 822, 'amount_msat': 190473, 'parent_partid': 666}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1389, 'amount_msat': 93596, 'parent_partid': 822}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1390, 'amount_msat': 96877, 'parent_partid': 822}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1566, 'amount_msat': 96877, 'parent_partid': 1390}, {'status': 'pending', 'failreason': 'No path found', 'partid': 441, 'amount_msat': 461656, 'parent_partid': 221}, {'status': 'failed', 'failreason': 'No path found', 'partid': 536, 'amount_msat': 235819, 'parent_partid': 441}, {'status': 'pending', 'failreason': 'No path found', 'partid': 667, 'amount_msat': 235819, 'parent_partid': 536}, {'status': 'pending', 'failreason': 'No path found', 'partid': 823, 'amount_msat': 110920, 'parent_partid': 667}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1031, 'amount_msat': 58725, 'parent_partid': 823}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1032, 'amount_msat': 52195, 'parent_partid': 823}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1257, 'amount_msat': 52195, 'parent_partid': 1032}, {'status': 'failed', 'failreason': 'No path found', 'partid': 824, 'amount_msat': 124899, 'parent_partid': 667}, {'status': 'pending', 'failreason': 'No path found', 'partid': 1391, 'amount_msat': 124899, 'parent_partid': 824}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1852, 'amount_msat': 66739, 'parent_partid': 1391}, {'status': 'failed', 'failreason': 'No path found', 'partid': 2078, 'amount_msat': 66739, 'parent_partid': 1852}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1853, 'amount_msat': 58160, 'parent_partid': 1391}, {'status': 'pending', 'failreason': 'No path found', 'partid': 537, 'amount_msat': 225837, 'parent_partid': 441}, {'status': 'pending', 'failreason': 'No path found', 'partid': 941, 'amount_msat': 102240, 'parent_partid': 537}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1458, 'amount_msat': 46907, 'parent_partid': 941}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1895, 'amount_msat': 46907, 'parent_partid': 1458}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1459, 'amount_msat': 55333, 'parent_partid': 941}, {'status': 'failed', 'failreason': 'No path found', 'partid': 942, 'amount_msat': 123597, 'parent_partid': 537}, {'status': 'pending', 'failreason': 'No path found', 'partid': 1082, 'amount_msat': 123597, 'parent_partid': 942}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1284, 'amount_msat': 65250, 'parent_partid': 1082}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1525, 'amount_msat': 65250, 'parent_partid': 1284}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1285, 'amount_msat': 58347, 'parent_partid': 1082}, {'status': 'failed', 'failreason': 'No path found', 'partid': 222, 'amount_msat': 783865, 'parent_partid': 92}, {'status': 'pending', 'failreason': 'No path found', 'partid': 294, 'amount_msat': 783865, 'parent_partid': 222}, {'status': 'failed', 'failreason': 'No path found', 'partid': 588, 'amount_msat': 407720, 'parent_partid': 294}, {'status': 'pending', 'failreason': 'No path found', 'partid': 988, 'amount_msat': 407720, 'parent_partid': 588}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1486, 'amount_msat': 207799, 'parent_partid': 988}, {'status': 'pending', 'failreason': 'No path found', 'partid': 1591, 'amount_msat': 207799, 'parent_partid': 1486}, {'status': 'pending', 'failreason': 'No path found', 'partid': 1981, 'amount_msat': 108379, 'parent_partid': 1591}, {'status': 'failed', 'failreason': 'No path found', 'partid': 2037, 'amount_msat': 51888, 'parent_partid': 1981}, {'status': 'failed', 'failreason': 'No path found', 'partid': 2038, 'amount_msat': 56491, 'parent_partid': 1981}, {'status': 'failed', 'failreason': 'No path found', 'partid': 2104, 'amount_msat': 56491, 'parent_partid': 2038}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1982, 'amount_msat': 99420, 'parent_partid': 1591}, {'status': 'failed', 'failreason': 'No path found', 'partid': 2130, 'amount_msat': 99420, 'parent_partid': 1982}, {'status': 'pending', 'failreason': 'No path found', 'partid': 1487, 'amount_msat': 199921, 'parent_partid': 988}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1592, 'amount_msat': 97442, 'parent_partid': 1487}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1983, 'amount_msat': 97442, 'parent_partid': 1592}, {'status': 'pending', 'failreason': 'No path found', 'partid': 1593, 'amount_msat': 102479, 'parent_partid': 1487}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1984, 'amount_msat': 53739, 'parent_partid': 1593}, {'status': 'failed', 'failreason': 'No path found', 'partid': 2039, 'amount_msat': 53739, 'parent_partid': 1984}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1985, 'amount_msat': 48740, 'parent_partid': 1593}, {'status': 'pending', 'failreason': 'No path found', 'partid': 589, 'amount_msat': 376145, 'parent_partid': 294}, {'status': 'pending', 'failreason': 'No path found', 'partid': 989, 'amount_msat': 180716, 'parent_partid': 589}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1115, 'amount_msat': 97298, 'parent_partid': 989}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1116, 'amount_msat': 83418, 'parent_partid': 989}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1665, 'amount_msat': 83418, 'parent_partid': 1116}, {'status': 'failed', 'failreason': 'No path found', 'partid': 990, 'amount_msat': 195429, 'parent_partid': 589}, {'status': 'pending', 'failreason': 'No path found', 'partid': 1117, 'amount_msat': 195429, 'parent_partid': 990}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1666, 'amount_msat': 88500, 'parent_partid': 1117}, {'status': 'failed', 'failreason': 'No path found', 'partid': 2005, 'amount_msat': 88500, 'parent_partid': 1666}, {'status': 'pending', 'failreason': 'No path found', 'partid': 1667, 'amount_msat': 106929, 'parent_partid': 1117}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1774, 'amount_msat': 50193, 'parent_partid': 1667}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1924, 'amount_msat': 50193, 'parent_partid': 1774}, {'status': 'failed', 'failreason': 'No path found', 'partid': 1775, 'amount_msat': 56736, 'parent_partid': 1667}]}
```

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2025-05-14 12:19:10 +09:30
Rusty Russell
b3b9d93fb0 pytest: fix flake in test_update_fee_reconnect.
If we grab l2's scratch_txid too early, it might not be the one which goes in the mempool:

```
2025-05-12T05:15:44.3947957Z     def test_update_fee_reconnect(node_factory, bitcoind):
...
2025-05-12T05:15:44.3962867Z         # Now shutdown cleanly.
2025-05-12T05:15:44.3963253Z         l1.rpc.close(chan)
2025-05-12T05:15:44.3963591Z     
2025-05-12T05:15:44.3963905Z         # And should put closing into mempool.
2025-05-12T05:15:44.3964671Z         l1.wait_for_channel_onchain(l2.info['id'])
2025-05-12T05:15:44.3965175Z >       l2.wait_for_channel_onchain(l1.info['id'])
2025-05-12T05:15:44.3965496Z 
2025-05-12T05:15:44.3965659Z tests/test_connection.py:2634: 
...
2025-05-12T05:15:44.3966616Z contrib/pyln-testing/pyln/testing/utils.py:1216: in wait_for_channel_onchain
2025-05-12T05:15:44.3967080Z     wait_for(lambda: txid in self.bitcoin.rpc.getrawmempool())
2025-05-12T05:15:44.3967429Z _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
2025-05-12T05:15:44.3967631Z 
2025-05-12T05:15:44.3967888Z success = <function LightningNode.wait_for_channel_onchain.<locals>.<lambda> at 0x7f0562d7f0a0>
2025-05-12T05:15:44.3968299Z timeout = 180
2025-05-12T05:15:44.3968408Z 
2025-05-12T05:15:44.3968515Z     def wait_for(success, timeout=TIMEOUT):
2025-05-12T05:15:44.3968805Z         start_time = time.time()
2025-05-12T05:15:44.3969041Z         interval = 0.25
2025-05-12T05:15:44.3969251Z         while not success():
2025-05-12T05:15:44.3969510Z             time_left = start_time + timeout - time.time()
2025-05-12T05:15:44.3969794Z             if time_left <= 0:
2025-05-12T05:15:44.3970278Z >               raise ValueError("Timeout while waiting for {}".format(success))
2025-05-12T05:15:44.3970894Z E               ValueError: Timeout while waiting for <function LightningNode.wait_for_channel_onchain.<locals>.<lambda> at 0x7f0562d7f0a0>
```
2025-05-14 12:19:10 +09:30
Rusty Russell
c6566cd6fd pytest: fix flake in test_zeroconf_forget
```
2025-05-12T04:37:57.4824338Z         else:
2025-05-12T04:37:57.4824626Z             # It will forget the older one.
2025-05-12T04:37:57.4825508Z >           l2.daemon.wait_for_log(r"UNUSUAL {}-chan#1: Forgetting channel: It has been {} blocks without the funding transaction ".format(l1.info['id'], blocks + 1))
```

This fails because l3 can still transmit, so the second channel can confirm in time.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2025-05-14 12:19:10 +09:30
Lagrang3
a899dea3e1 use amount_msat_mul_div operation to compute fees
Changelog-None

Signed-off-by: Lagrang3 <lagrang3@protonmail.com>
2025-05-13 19:16:51 +09:30
Lagrang3
b379500d21 askrene: fixed routing in high capacity channels
We may introduce high capacity channels in askrene to represent problems
with multiple destinations (eg. multiple blinded paths) or to solve
self-payments. The integer computation of the deliverable amount through
these channels (I tested this with a channel with 21M bitcoin) would
fail due to an integer overflow in the function `amount_msat_sub_fee`,
21M BTC = 21 x 10^17 msat, which overflows u64 integers when multiplied
by 10^6. We have fixed `amount_msat_sub_fee` operations, so that it
doesn't overflow.

Changelog-Fixed: askrene: fixed routing in high capacity channels.

Signed-off-by: Lagrang3 <lagrang3@protonmail.com>
2025-05-13 19:16:51 +09:30
Lagrang3
81417958d4 askrene-inform-channel: change order of operations
Change order of operations to ensure that askrene-inform-channel with
inform=constrained computes the correct upper bound on the liquidity:

    upperBound = reserves + amount - 1

With the previous order of operations in the case amount=0 we would get:

    upperBound = reserves

instead of
    upperBound = reserves - 1

Changelog-None

Signed-off-by: Lagrang3 <lagrang3@protonmail.com>
2025-05-13 19:14:57 +09:30
ShahanaFarooqui
52a9bb1007 Separate reckless utility (1) and reckless rpc (7) documentation
Changelog-None.
2025-05-13 19:11:27 +09:30
Lagrang3
a90de8dcc7 sendonion: add total_amount_msat parameter
Changelog-Added: sendonion: a new paramter total_amount_msat to make MPP payments with sendpay and sendonion compatible.

[ Reordered to put new parameter at the end --RR ]
Signed-off-by: Lagrang3 <lagrang3@protonmail.com>
2025-05-13 15:00:50 +09:30
Dusty Daemon
5d16bb0533 splice: Wait for mempool in tests
In some cases the CI is so quick and / or slow that the mempool doesn’t have the transaction by the time we’re looking for it.

Move the mempool check into a wait_for.
2025-05-13 14:52:15 +09:30
Dusty Daemon
8d247fa9e6 splice: Add more explicit error messages
To make failure casee more clear
2025-05-13 14:52:15 +09:30
Dusty Daemon
44e338daa0 splice: Message sorting should be using txid parsing
Update from old channel_id non-spec version
2025-05-13 14:52:15 +09:30
Dusty Daemon
3f626371c3 splice: Verbose logging for Eclair interop 2025-05-13 14:52:15 +09:30
Dusty Daemon
3d01b01dda splice: Add test for splice RBF
A test that does an RBF and a few HTLCs at various phases of the splice RBF
2025-05-13 14:52:15 +09:30
Dusty Daemon
4466286167 splice: Changing encoding of TLV funding_txid
Using the wrong encoding flips the bytes. We have to use sha256 as the spec says to prevent them from flipping.
2025-05-13 14:52:15 +09:30
Dusty Daemon
9a3c3c0a3e splice: Improve log message for handle_peer_commit_sig 2025-05-13 14:52:15 +09:30
Dusty Daemon
8741e75303 splice: Fix txid watch for splice RBF
Remove a check that prevents txid watching on splice RBF attempts.
2025-05-13 14:52:15 +09:30
Dusty Daemon
7bf544db02 splice: Add support for tx_abort during RBF
We do this by adding a specific txid the tx_abort applies to and performing checks based on that.

If the txid is NULL or unrecognized than no inflights are dropped from DB. If we recognize it than we do the check to see if we signed it and, if not, we let lightningd remove it from DB.
2025-05-13 14:52:15 +09:30
Dusty Daemon
cc11d95564 splice: Update test for new reestablish behavior
New reestablish behvaior allows splices to resume on reestablish if only commit sigs were exchanged.

Update the `test_commit_crash_splice` to reflect this (and turn it back on).
2025-05-13 14:52:15 +09:30
Dusty Daemon
7f90e9679b gossip: Limit announcement sigs reply
A splice where reestablish happens at the right moment causes an infinite loop of announcement signatures being sent back and forth.

Limit the announcement sigs we send in response to announcement sigs to once per channel session.

ChangelogNone
2025-05-13 14:52:15 +09:30
Dusty Daemon
0f109d0155 splice: Add verbose log messages for new reestablish TLV 2025-05-13 14:52:15 +09:30
Dusty Daemon
357b4b503d splice: Enable user splice RBF
Allow user’s to RBF existing splices. For now this is done by simple executing an additional splice command, in the future this will can also be done with dedicated RPCs.

Changelog-Added: Enabled the ability to RBF splices
2025-05-13 14:52:15 +09:30
Dusty Daemon
0615c156f5 splice: Splice script should not abort on sign
The result of splice_signed can fail for many reasons that are non-critical (already in mempool for instance).

Don’t abort channels in this case as that causes a force close.
2025-05-13 14:52:15 +09:30
Dusty Daemon
398bd1cb8d splice: Enable the receiving of splice RBF
Turn on the receiving of splice RBF attempts.
2025-05-13 14:52:15 +09:30
Dusty Daemon
b231db3f65 splice: Only send or recv commit sig if needed
Be more conservative about when we request of send commit sig for splice to match the Eclair behavior.
2025-05-13 14:52:15 +09:30
Dusty Daemon
c02f89baa8 splice: Decrement next_commitment_number for Eclair
Eclair requires `next_commitment_number` to be decremented to resend the individual splice commitment_signed message.
2025-05-13 14:52:15 +09:30
Dusty Daemon
e928817fa7 splice: Update to Eclair style of reestablish
Update to use Eclair’s spec’d version of reestablish.

Changelog-None
2025-05-13 14:52:15 +09:30
Dusty Daemon
dd962225ef splice: Allow commit_sig batch in any order
Other implementations are sending commit_sig batches in different orders. We add support for them being in any order by ordering the batch of messages after receiving them.

Changelog-Changed: Increase interop compatability by loosening requirement that commitment signed messages be received in a particular order and sorting them internally.
2025-05-13 14:52:15 +09:30
Dusty Daemon
b749128447 splice: Update our_funds during splice_lock
The value of `our_funds` inlightningd is the funds added to the channel during creation. Splicing is a quasi-creation event. This change makes our pending funds be considered funding funds at the moment of splice confirmation.

Changelog-None
2025-05-13 14:52:15 +09:30
Dusty Daemon
afdc010d96 splice: Clean error statement
Error statement was misformatted and caused a crash instead of reporting the error.

Changelog-None
2025-05-13 14:52:15 +09:30
Dusty Daemon
c9c56e340d PSBT: Clean up PSBT chunk allocations
Cleaning up the memory hierarchy of PSBT usage in splicing and `psbt_finalize_input`
2025-05-13 14:52:15 +09:30
Dusty Daemon
1621b67d34 splice: Prevent user from signing an unfinal splice
An extra check to ensure the user doesn’t try to sign a splice that wasn’t finalized.
2025-05-13 14:52:15 +09:30
Dusty Daemon
10616b0694 PSBT: tal_wally updates and docs
Default wally_tal_ctx to NULL, add extra asserts and tal_checks, and documentation explaning the usage of tal_wally_start/end.

Changelog-None
2025-05-13 14:52:15 +09:30
Dusty Daemon
5e5ed774fc PSBT: Add audi_psbt routine
A routine that audit’s and asserts PSBT memory to confirm it has a sane memory allocation hierarchy.

Changelog-None
2025-05-13 14:52:15 +09:30
Dusty Daemon
23e80d9e81 PSBT: Change bitcoin_tx routine to use TAKES
`bitcoin_tx_with_psbt` would somewhat opaquely steal the passed `psbt` value.

This caused a bug where code made a `bitcoin_tx` using a psbt without realizing the value was stolen. Because the resulting `bitcoin_tx` was placed in tmpctx it was not immediately clear that using `psbt` afterwards was an error until the tmpctx was cleared — creating a valgrind backtrace far from the actual issue.

Switching to the routine to using TAKES and adding documentation in the header, makes it explicitly clear which operation the user is doing — helping prevent future regressions of this kind.

Changelog-None
2025-05-13 14:52:15 +09:30
Dusty Daemon
58252a53a6 splice: Use clone instead of steal for PSBT
Update splice flows to use the new `clone_psbt` method instead of stealing back and forth.
2025-05-13 14:52:15 +09:30
Dusty Daemon
e8e30a420c PSBT: Fix compare to not mutate memory
PSBT changeset routines were using linearize_output which mutated the memory of the objects it was comparing.

This commit fixes that and also cleans up the memory usage to be more clear and more guarentee there is no memory corruption.

Changelog-None
2025-05-13 14:52:15 +09:30
Dusty Daemon
721f36831e splice: Add check for correct txid in splice_locked
Check that the peer sent the correct txid in their `splice_locked` message.

We have to check this later on in `check_mutal_splice_locked` so we store the value in `splice_state`
2025-05-13 14:52:15 +09:30
Richard Myers
940b6a3af2 splice: Add splice_txid to splice_locked message 2025-05-13 14:52:15 +09:30
Richard Myers
168c3b0d55 Add debug outputs and fix prevtx issue 2025-05-13 14:52:15 +09:30
Dusty Daemon
9d0b2ddf0c Splice: Update PSBT version handling
Upscale user provided PSBTs to v2 and convert them back to user preference when returned.
2025-05-13 14:52:15 +09:30
Dusty Daemon
a953a12573 splice: Resume splice_locked on reestablish
A new case where `splice_locked` must be sent again on reestablish.

This handles the case where `splice_locked` did not complete locally or remotely and must be resumed.
2025-05-13 14:52:15 +09:30
Dusty Daemon
2bd39f270e splice: Add locked field to inflight db
This is needed to remember if a splice was locked and reconnect occurs mid `splice_locked` attempted so it can be resumed in reestablish.
2025-05-13 14:52:15 +09:30
Dusty Daemon
bed2796032 Splice: Rotating funding pubkey fix
Interop testing with Eclair revealed an issue with remote funding key rotation.

This searches for the funding output using the rotated remote funding pubkey instead of the furrent funding pubkey.

Also update the variable name to be more clear which this represents.

Changelog-Changed: Interop fixes for compatability with Eclair
2025-05-13 14:52:15 +09:30
Lagrang3
7343502c69 hsmd: refactor hsmd_init
Add preapprove_check capabilities:
WIRE_HSMD_PREAPPROVE_INCOICE_CHECK and
WIRE_HSMD_PREAPPROVE_KEYSEND_CHECK to the capabilities array
if dev_no_preapprove_check is not set.
Do not assume those occupy the last two slots in the array.

Changelog-None

Signed-off-by: Lagrang3 <lagrang3@protonmail.com>
2025-05-13 13:19:03 +09:30
Lagrang3
50cdf05a4a add signmessagewithkey RPC
signmessagewithkey: allows to sign a message with a key associated with
one bitcoin address in our wallet.

Changelog-Added: add a new rpc command signmessagewithkey to sign input messages with keys from our wallet.

Signed-off-by: Lagrang3 <lagrang3@protonmail.com>
2025-05-13 13:19:03 +09:30
Lagrang3
5f0c24b441 add devtool/bip137-verifysignature utility
To validate BIP137 signatures produced by core-lightning in tests.

Changelog-None.

Signed-off-by: Lagrang3 <lagrang3@protonmail.com>
2025-05-13 13:19:03 +09:30
Lagrang3
b6388c710f HSMD: add new wire BIP137 sign message API
Changelog-Added: HSMD: add new wire API to sign messages with bitcoin wallet keys according to BIP137.

Signed-off-by: Lagrang3 <lagrang3@protonmail.com>
2025-05-13 13:19:03 +09:30
ShahanaFarooqui
49bcc94f3b tests: Fix test_emergencyrecover to check for ChannelReestablish
Make sure we are sending bogus channel reestablish after recovering from
emergency.recover file and peer storage backup.

Key Changes:
 - Add wait_for_log() with appropriate debug statements
2025-05-13 09:48:42 +09:30
Aditya Sharma
39a2893688 Workaround for LND to cause a force-close on our channel
Unfortunately LND does not force close the channels on receiving an error,
they blame us for this behaviour (abb1e3463f/htlcswitch/link.go (L2119))

To fix this we will send them a Bogus Channel Reestablish with 0 commitment_number and invalid last_per_commit_secret.

Key Changes:
  - In connect_activate_subd, if we detect a stub channel, we serialize and send a bogus channel_reestablish message.

Changelog-Fixed: Fixing LND's non responsive behaviour on receiving an error.
2025-05-13 09:48:42 +09:30
Rusty Russell
99ef16fd71 doc: clarify that all with utxos spends all those utxos only.
Reported-by: https://github.com/michaelWuensch
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
Changelog-None: trivial
2025-05-12 13:00:50 +09:30
Rusty Russell
0824d12849 bcli: don't try asking non-full nodes for blocks.
Suggested-by: @NicolasDorier
Closes: https://github.com/ElementsProject/lightning/issues/8078
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
Changelog-Changed: Protocol: we no longer try asking for blocks from bitcoind's peers if they don't store blocks.
2025-05-12 10:38:25 +09:30
Rusty Russell
e76a7a971e pytest: fix flake in test_anchorspend_using_to_remote
Make sure all nodes see all channels:

```
2025-05-09T06:07:42.6214730Z >       route = l1.rpc.getroute(l3.info['id'], amt, 1)['route']
2025-05-09T06:07:42.6215091Z 
2025-05-09T06:07:42.6215239Z tests/test_closing.py:4199: 
...
2025-05-09T06:07:42.6241237Z E           pyln.client.lightning.RpcError: RPC call failed: method: getroute, payload: {'id': '035d2b1192dfba134e10e540875d366ebc8bc353d5aa766b80c090b39c3a5d885d', 'amount_msat': 100000000, 'riskfactor': 1, 'cltv': 9}, error: {'code': -32602, 'message': '035d2b1192dfba134e10e540875d366ebc8bc353d5aa766b80c090b39c3a5d885d: unknown destination node_id (no public channels?)'}
```

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2025-05-11 11:25:40 +09:30
Rusty Russell
65dccea5bd pytest: fix flake in test_reconnect_signed
We can fail the fundchannel because of a reconnect race: funder tells
us to reconnect so fast that we are still cleaning up from last time.

We deliberately defer clean up, to give the subds a chance to process any
final messages.  However, on reconnection we force them to exit immediately:
but this causes new `connect` commands to see the exit and fail.

The workaround is to do this cleanup when a `connect` command is
issued (as well as the current case, which covers an automatic
reconnection or an incoming reconnection)

```
2025-05-09T00:40:37.1769508Z     def test_reconnect_signed(node_factory):
2025-05-09T00:40:37.1770273Z         # This will fail *after* both sides consider channel opening.
2025-05-09T00:40:37.1770850Z         disconnects = ['<WIRE_FUNDING_SIGNED']
2025-05-09T00:40:37.1771298Z         if EXPERIMENTAL_DUAL_FUND:
2025-05-09T00:40:37.1771735Z             disconnects = ['<WIRE_COMMITMENT_SIGNED']
2025-05-09T00:40:37.1772155Z     
2025-05-09T00:40:37.1772598Z         l1 = node_factory.get_node(may_reconnect=True, disconnect=disconnects)
2025-05-09T00:40:37.1773210Z         l2 = node_factory.get_node(may_reconnect=True)
2025-05-09T00:40:37.1773632Z     
2025-05-09T00:40:37.1773917Z         l1.fundwallet(2000000)
2025-05-09T00:40:37.1774268Z     
2025-05-09T00:40:37.1774611Z         l1.rpc.connect(l2.info['id'], 'localhost', l2.port)
2025-05-09T00:40:37.1775151Z >       l1.rpc.fundchannel(l2.info['id'], CHANNEL_SIZE)
2025-05-09T00:40:37.1775388Z 
2025-05-09T00:40:37.1775485Z tests/test_connection.py:667:
...
2025-05-09T00:40:37.1799527Z >           raise RpcError(method, payload, resp['error'])
2025-05-09T00:40:37.1800993Z E           pyln.client.lightning.RpcError: RPC call failed: method: fundchannel, payload: {'id': '022d223620a359a47ff7f7ac447c85c46c923da53389221a0054c11c1e3ca31d59', 'amount': 50000, 'announce': True}, error: {'code': -1, 'message': 'Disconnected', 'data': {'id': '022d223620a359a47ff7f7ac447c85c46c923da53389221a0054c11c1e3ca31d59', 'method': 'openchannel_update'}}
```

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2025-05-11 11:25:40 +09:30
Rusty Russell
9ce3f5dde4 askrene: fix API breakage, add tests.
We cannot add new parameters in the middle, since we accept parameters by JSON
array as well as by dicts.  In fact, this broke tests, but due to unrelated
breakage in the GitHub "Automerge" functionality, it got applied as
556e38c838 ("askrene-bias-channel: bias call add
up.").

Also add tests, and a better Changelog line.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
Changelog-Added: JSON-RPC: `askrene-bias-channel` now has a `relative` option to add, rather than replace, a channel bias.
2025-05-11 11:25:40 +09:30
Rusty Russell
628d002c59 pytest: fix flake in test_listforwards_and_listhtlcs
We need to make sure the close tx is generated where we expect, so the following code
doesn't wait foreverL

```
2025-05-08T04:31:31.1071194Z >       assert l2.rpc.wait('htlcs', 'deleted', 3)['deleted'] == 5
2025-05-08T04:31:31.1071518Z 
2025-05-08T04:31:31.1071645Z tests/test_misc.py:3398: 
...
2025-05-08T04:31:31.1079841Z E       Failed: Timeout >1800.0s
```

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2025-05-11 11:25:40 +09:30
Rusty Russell
a97527212c GitHub: fix "Automerge" button to *actually* depend on tests passing.
I've been bitten by this several times: skipping the test seems to make it OK
for GH!

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2025-05-11 11:25:40 +09:30
Alex Myers
8da55128ed misc: update Alex's gpg key
A subkey needed updating.

Changelog-None
2025-05-09 13:03:51 -05:00
Rusty Russell
9a967d6770 gossipd: don't try to connect to ourselves if we need more peers.
Reported-by: JssDWt
Closes: https://github.com/ElementsProject/lightning/issues/8200
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
Changelog-None: trivial
2025-05-08 15:30:14 -05:00
Rusty Russell
1521b92e41 CI: Use eatmydata to speed up test runs.
We don't care about data persistence, and this suppresses all sync calls (speeding
sqlite3 specifically).

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2025-05-08 14:01:38 +09:30
Rusty Russell
b472baeab5 CI: don't wait on update-docs-examples
It's disabled.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2025-05-08 14:01:38 +09:30
Rusty Russell
1125130db0 CI: don't abandon other runs just because one fails.
This significantly slows down the cycle when we have flakes (it's good if
the tree is completely broken though!).

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2025-05-08 14:01:38 +09:30
Rusty Russell
fff054f8ee gossipd: fix false memleak positive in gossmap_manage
If there are pending channel announcements, they'll look like a leak unless we scan into
the maps.

```
lightningd-2 2025-05-01T07:27:03.922Z **BROKEN** gossipd: MEMLEAK: 0x60d000000478
lightningd-2 2025-05-01T07:27:03.923Z **BROKEN** gossipd:   label=gossipd/gossmap_manage.c:595:struct pending_cannounce
lightningd-2 2025-05-01T07:27:03.923Z **BROKEN** gossipd:   alloc:
lightningd-2 2025-05-01T07:27:03.923Z **BROKEN** gossipd:     /home/runner/work/lightning/lightning/ccan/ccan/tal/tal.c:488 (tal_alloc_)
lightningd-2 2025-05-01T07:27:03.923Z **BROKEN** gossipd:     /home/runner/work/lightning/lightning/gossipd/gossmap_manage.c:595 (gossmap_manage_channel_announcement)
lightningd-2 2025-05-01T07:27:03.923Z **BROKEN** gossipd:     /home/runner/work/lightning/lightning/gossipd/gossipd.c:205 (handle_recv_gossip)
lightningd-2 2025-05-01T07:27:03.923Z **BROKEN** gossipd:     /home/runner/work/lightning/lightning/gossipd/gossipd.c:300 (connectd_req)
lightningd-2 2025-05-01T07:27:03.923Z **BROKEN** gossipd:     /home/runner/work/lightning/lightning/common/daemon_conn.c:35 (handle_read)
lightningd-2 2025-05-01T07:27:03.923Z **BROKEN** gossipd:     /home/runner/work/lightning/lightning/ccan/ccan/io/io.c:60 (next_plan)
lightningd-2 2025-05-01T07:27:03.923Z **BROKEN** gossipd:     /home/runner/work/lightning/lightning/ccan/ccan/io/io.c:422 (do_plan)
lightningd-2 2025-05-01T07:27:03.923Z **BROKEN** gossipd:     /home/runner/work/lightning/lightning/ccan/ccan/io/io.c:439 (io_ready)
lightningd-2 2025-05-01T07:27:03.923Z **BROKEN** gossipd:     /home/runner/work/lightning/lightning/ccan/ccan/io/poll.c:455 (io_loop)
lightningd-2 2025-05-01T07:27:03.923Z **BROKEN** gossipd:     /home/runner/work/lightning/lightning/gossipd/gossipd.c:660 (main)
lightningd-2 2025-05-01T07:27:03.923Z **BROKEN** gossipd:     ../sysdeps/nptl/libc_start_call_main.h:58 (__libc_start_call_main)
lightningd-2 2025-05-01T07:27:03.924Z **BROKEN** gossipd:     ../csu/libc-start.c:392 (__libc_start_main_impl)
lightningd-2 2025-05-01T07:27:03.924Z **BROKEN** gossipd:   parents:
lightningd-2 2025-05-01T07:27:03.924Z **BROKEN** gossipd:     gossipd/gossmap_manage.c:475:struct gossmap_manage
```

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2025-05-08 14:01:38 +09:30
Rusty Russell
a22d5dc9f4 lightningd: use static buffer for common log path.
This speeds logging slightly, but most of the time is actually
spent in fflush() (which we need).

Result (10 runs, eatmydata):
	FAILED tests/test_connection.py::test_bench - assert 24.086638-25.347475(24.6901+/-0.4) == 0

This is an 8% performance improvement (over the entire series), which is not bad.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2025-05-08 14:01:38 +09:30
Rusty Russell
de7db8a1ba lightningd: keep a hash table for plugin notifications.
This means we don't have to iterate through all plugins, making
our "do we even have to construct this notification" optimization
much more efficient.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2025-05-08 14:01:38 +09:30
Rusty Russell
974d3afff7 lightningd: optimize notifications.
If nobody is subscribed, have notify_start return NULL and the caller
can skip serialization.  This is particularly useful for the "log"
notification which can get called a lot.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2025-05-08 14:01:38 +09:30
Rusty Russell
2d7f268465 lightningd: don't allocate to print node_id for logging.
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2025-05-08 14:01:38 +09:30
Rusty Russell
b387b26cb3 common: don't enable steal loop checking unless we're doing memleak checking.
Before:
92.26076173782349
91.9576666355133
90.92732524871826

After:
90.5989830493927
88.10309219360352
90.07689118385315
2025-05-08 14:01:38 +09:30
Rusty Russell
3cd589d2ce bench: why does sending payments take so long under CI?
To run, use:
	VALGRIND=0 TEST_BENCH=1 eatmydata pytest tests/test_connection.py::test_bench

Example of running on my laptop (without --enable-debugbuild, over of 10 runs):

	FAILED tests/test_connection.py::test_bench - assert 47.403406-49.191765(48.343+/-0.48) == 0

With eatmydata:

	FAILED tests/test_connection.py::test_bench - assert 25.867860-27.549878(26.5762+/-0.5) == 0

You can also run perf on l1 once it's running:

	perf record --call-graph dwarf -q -p $(cat /tmp/ltests-*/test_bench_1/lightning-1/lightningd-regtest.pid)

Then ^C after 10 seconds and run "perf report".

Things which stood out:

1. Tracing in db_exec_prepared_v2 (fixed in another PR)

   31.12%     0.04%  lightningd  lightningd            [.] db_exec_prepared_v2
   - 31.08% db_exec_prepared_v2
      + 22.96% db_sqlite3_exec
      + 4.46% trace_span_end
      + 1.77% trace_span_start
      + 1.11% trace_span_tag
      + 0.72% tal_free

2. Logging:

   - 16.03% logv
      - 8.15% maybe_print
         - log_to_files
            + 4.51% __GI__IO_fflush (inlined)
            + 1.97% tal_fmt_
            + 0.51% __GI___strftime_l (inlined)

3. Notification (when nothing is listening) in notify_log:

      - 6.84% maybe_notify_log
         - notify_log
            + 3.37% notify_send
            + 1.75% notify_start
            + 1.71% log_notification_serialize
        0.56% new_log_entry

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2025-05-08 14:01:38 +09:30
Rusty Russell
e27dee0fc4 connectd: fix nagle disabling logic.
Our CORK logic was wrong, and it's better to use Nagle anyway:
we disable Nagle just before sending timing-critical messages.

Time for 100 (failed) payments:

Before:
	148.8573575

After:
	10.7356977

Note this revealed a timing problem in test_reject_invalid_payload: we would
miss the cause of the sendonion failure, and waitsendpay would be called
*after* it had failed, so simply returns "Payment failure reason unknown".

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
Changelog-Fixed: Protocol: Removed 200ms latency from sending commit/revoke messages.
2025-05-08 14:01:38 +09:30
Rusty Russell
863aac40c6 pytest: test for lack of nagle delay.
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2025-05-08 14:01:38 +09:30
Rusty Russell
4ba7fabdee pytest: fix flake in test_channel_lease_unilat_closes
We need to make sure the lease starts a the block we expect:

```
        # Note that l3 has the whole lease delay (minus blocks already mined)
        _, _, l3blocks = l3.wait_for_onchaind_tx('OUR_DELAYED_RETURN_TO_WALLET',
                                                 'OUR_UNILATERAL/DELAYED_OUTPUT_TO_US')
>       assert l3blocks == 4032 - 6 - 2 - 1
E       assert 4022 == (((4032 - 6) - 2) - 1)

tests/test_closing.py:985: AssertionError
```

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2025-05-08 14:01:38 +09:30
Rusty Russell
5a855b8d46 pytest: fix flake in test_onionmessage_forward_fail
We can fail to connect because l3 connects to l2 at the same time l2 connects to l3:

```
        # The plugin in l2 fixes up the connection, so this works!
>       l1.rpc.fetchinvoice(offer['bolt12'])

tests/test_connection.py:4792:
...
        elif "error" in resp:
>           raise RpcError(method, payload, resp['error'])
E           pyln.client.lightning.RpcError: RPC call failed: method: fetchinvoice, payload: {'offer': 'lno1qgsqvgnwgcg35z6ee2h3yczraddm72xrfua9uve2rlrm9deu7xyfzrcgqgqjczs7w3jhxazldahxjmmwd4jhxumpvaj47en0wfmkzunytanxz6tvzcssxhftzxfdlwsnfcgw2sy8t5mxa0ytcdfat2nkdwqvpy9nnsa9mzza'}, error: {'code': 1005, 'message': 'Timeout waiting for response'}
```

From logs:

```
lightningd-2 2025-05-07T21:20:54.367Z DEBUG   035d2b1192dfba134e10e540875d366ebc8bc353d5aa766b80c090b39c3a5d885d-connectd: peer_out WIRE_INIT
lightningd-2 2025-05-07T21:20:54.367Z DEBUG   035d2b1192dfba134e10e540875d366ebc8bc353d5aa766b80c090b39c3a5d885d-connectd: Connect IN
``

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2025-05-08 14:01:38 +09:30
Rusty Russell
59a29a45db pytest: fix race in test_peer_anchor_push.
We have to make sure the new tx has been received by bitcoind, otherwise we
could be examining the previous:

```
>           check_feerate(l2, total_feerate_perkw, feerate)

tests/test_closing.py:4053: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

node = <fixtures.LightningNode object at 0x7f645789ee90>
actual_feerate = 14000.0, expected_feerate = 15000

    def check_feerate(node, actual_feerate, expected_feerate):
        # Feerate can't be lower.
>       assert actual_feerate > expected_feerate - 2
```

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2025-05-08 14:01:38 +09:30
Rusty Russell
07d8c60902 pytest: make test_peer_anchor_push robust against short sig generation.
This happens one time in 256:

```
2025-05-06T11:00:43.2201832Z >           assert feerate - 1 < total_feerate_perkw < feerate + 1
2025-05-06T11:00:43.2202133Z E           assert 12005.233318796338 < (12000 + 1)
```

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2025-05-08 14:01:38 +09:30
Rusty Russell
ccebaed019 pytest: test_fundpsbt_feerates: don't expect correct weight if we have a short signature.
```
>               assert txinfo['weight'] == prep['estimated_final_weight']
E               assert 755 == 756
```

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2025-05-08 14:01:38 +09:30
Rusty Russell
b3dda01213 pytest: fix occasional short tx in test_onchain_slow_anchor
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2025-05-08 14:01:38 +09:30
Rusty Russell
4058d88f8a pytest: fix typo in test_anchorspend_using_to_remote
Presumably we want to wait for htlcs to be all resolved here.  With the speedup,
this failed under Postgres:

```
>       wait_for(lambda: only_one(l2.rpc.listpeerchannels(l3.info['id'])['channels'])['htlcs'] != [])

tests/test_closing.py:4191:
```

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2025-05-08 14:01:38 +09:30
Rusty Russell
2a42125278 pytest: fix flake in test_rbf_to_chain_before_commit
Once we speed things up, this can receive COMMITMENT_SIGNED, and hence succeed.  Let's
drop on receive, not send!

```
2025-05-06T06:07:51.5997333Z         # Peers try RBF, break on initial COMMITMENT_SIGNED
2025-05-06T06:07:51.5997855Z         bump = l1.rpc.openchannel_bump(chan_id, chan_amount, initpsbt['psbt'])
2025-05-06T06:07:51.5998214Z >       with pytest.raises(RpcError):
2025-05-06T06:07:51.5998542Z E       Failed: DID NOT RAISE <class 'pyln.client.lightning.RpcError'>
```

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2025-05-08 14:01:38 +09:30
Rusty Russell
86e5b146b6 pytest: fix flake in test_rbf_reconnect_tx_construct
Once we speed things up, we can *receive* commitment_signed before we disconnect
due to sending ours: in this case, we *will* have a scratch tx.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2025-05-08 14:01:38 +09:30
Rusty Russell
e20efa17e2 msggen: regenerate.
Somehow GitHub's "Enable auto-merge" merged the PR without it actually passing.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2025-05-08 13:10:41 +09:30
Rusty Russell
0a94f3b570 connectd: remove DNS seed lookups.
DNS seeds have been down/offline for a while, and this code (which
blocks!) has been a source of trouble.  We should probably use a
canned set of "known nodes" if we want to bootstrap.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
Changelog-Changed: Protocol: we no longer use DNS seeds for peer lookup fallbacks.
Fixes: https://github.com/ElementsProject/lightning/issues/7913
2025-05-08 12:54:09 +09:30
Rusty Russell
c779abdcd2 connectd: don't run more than one reconnect timer at once.
From grubles' logs:

```
2025-01-06T15:30:31.449Z DEBUG   lightningd: attempting connection to 035ca2fe4793a5e789ce846062eb4834f573c060d9200ce77544a29b48a0aa5923 for additional gossip
2025-01-06T15:30:31.449Z DEBUG   035ca2fe4793a5e789ce846062eb4834f573c060d9200ce77544a29b48a0aa5923-connectd: Adding 0 addresses to important peer
2025-01-06T15:30:31.449Z DEBUG   035ca2fe4793a5e789ce846062eb4834f573c060d9200ce77544a29b48a0aa5923-connectd: Failed connected out: Unable to connect, no address known for peer
2025-01-06T15:30:31.449Z DEBUG   035ca2fe4793a5e789ce846062eb4834f573c060d9200ce77544a29b48a0aa5923-connectd: Will try reconnect in 300 seconds
2025-01-06T15:30:32.037Z DEBUG   035ca2fe4793a5e789ce846062eb4834f573c060d9200ce77544a29b48a0aa5923-connectd: Failed connected out: Unable to connect, no address known for peer
2025-01-06T15:30:32.037Z DEBUG   035ca2fe4793a5e789ce846062eb4834f573c060d9200ce77544a29b48a0aa5923-connectd: Will try reconnect in 300 seconds
2025-01-06T15:30:32.428Z DEBUG   035ca2fe4793a5e789ce846062eb4834f573c060d9200ce77544a29b48a0aa5923-connectd: Failed connected out: Unable to connect, no address known for peer
2025-01-06T15:30:32.428Z DEBUG   035ca2fe4793a5e789ce846062eb4834f573c060d9200ce77544a29b48a0aa5923-connectd: Will try reconnect in 300 seconds
2025-01-06T15:30:32.680Z DEBUG   035ca2fe4793a5e789ce846062eb4834f573c060d9200ce77544a29b48a0aa5923-connectd: Failed connected out: Unable to connect, no address known for peer
2025-01-06T15:30:32.681Z DEBUG   035ca2fe4793a5e789ce846062eb4834f573c060d9200ce77544a29b48a0aa5923-connectd: Will try reconnect in 300 seconds
2025-01-06T15:30:33.468Z DEBUG   035ca2fe4793a5e789ce846062eb4834f573c060d9200ce77544a29b48a0aa5923-connectd: Failed connected out: Unable to connect, no address known for peer
2025-01-06T15:30:33.469Z DEBUG   035ca2fe4793a5e789ce846062eb4834f573c060d9200ce77544a29b48a0aa5923-connectd: Will try reconnect in 300 seconds
2025-01-06T15:30:33.471Z DEBUG   035ca2fe4793a5e789ce846062eb4834f573c060d9200ce77544a29b48a0aa5923-connectd: Failed connected out: Unable to connect, no address known for peer
2025-01-06T15:30:33.471Z DEBUG   035ca2fe4793a5e789ce846062eb4834f573c060d9200ce77544a29b48a0aa5923-connectd: Will try reconnect in 300 seconds
2025-01-06T15:30:33.935Z DEBUG   035ca2fe4793a5e789ce846062eb4834f573c060d9200ce77544a29b48a0aa5923-connectd: Failed connected out: Unable to connect, no address known for peer
2025-01-06T15:30:33.935Z DEBUG   035ca2fe4793a5e789ce846062eb4834f573c060d9200ce77544a29b48a0aa5923-connectd: Will try reconnect in 300 seconds
2025-01-06T15:30:34.125Z DEBUG   035ca2fe4793a5e789ce846062eb4834f573c060d9200ce77544a29b48a0aa5923-connectd: Failed connected out: Unable to connect, no address known for peer
2025-01-06T15:30:34.125Z DEBUG   035ca2fe4793a5e789ce846062eb4834f573c060d9200ce77544a29b48a0aa5923-connectd: Will try reconnect in 300 seconds
2025-01-06T15:30:35.496Z DEBUG   035ca2fe4793a5e789ce846062eb4834f573c060d9200ce77544a29b48a0aa5923-connectd: Failed connected out: Unable to connect, no address known for peer
2025-01-06T15:30:35.497Z DEBUG   035ca2fe4793a5e789ce846062eb4834f573c060d9200ce77544a29b48a0aa5923-connectd: Will try reconnect in 300 seconds
2025-01-06T15:30:35.623Z DEBUG   035ca2fe4793a5e789ce846062eb4834f573c060d9200ce77544a29b48a0aa5923-connectd: Failed connected out: Unable to connect, no address known for peer
2025-01-06T15:30:35.623Z DEBUG   035ca2fe4793a5e789ce846062eb4834f573c060d9200ce77544a29b48a0aa5923-connectd: Will try reconnect in 300 seconds
2025-01-06T15:30:35.751Z DEBUG   035ca2fe4793a5e789ce846062eb4834f573c060d9200ce77544a29b48a0aa5923-connectd: Failed connected out: Unable to connect, no address known for peer
2025-01-06T15:30:35.751Z DEBUG   035ca2fe4793a5e789ce846062eb4834f573c060d9200ce77544a29b48a0aa5923-connectd: Will try reconnect in 300 seconds
2025-01-06T15:30:35.892Z DEBUG   035ca2fe4793a5e789ce846062eb4834f573c060d9200ce77544a29b48a0aa5923-connectd: Failed connected out: Unable to connect, no address known for peer
2025-01-06T15:30:35.892Z DEBUG   035ca2fe4793a5e789ce846062eb4834f573c060d9200ce77544a29b48a0aa5923-connectd: Will try reconnect in 300 seconds
```

We promised to wait 300 seconds!

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2025-05-08 12:54:09 +09:30
Lagrang3
556e38c838 askrene-bias-channel: bias call add up.
The channel bias feature is not being used yet by any plugin, so this
hopefully doesn't break any working code.
When askrene-bias-channel is called the bias quantity is added on top of
any previous biased already present on that channel instead of
overwriting it.

Changelog-Changed: askrene-bias-channel: bias call add up.

Signed-off-by: Lagrang3 <lagrang3@protonmail.com>
2025-05-08 12:28:57 +09:30
Rusty Russell
c81ec4fe76 lightningd: deprecate (undocumented!) "unknown" old_state field in channel_state_changed notification.
Reported-by: daywalker90
Changelog-Deprecated: JSON-RPC: channel_state_changed notification field `old_state` value "unknown" (it will be omitted, instead)
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2025-05-08 10:49:31 +09:30
Rusty Russell
8e41ee4eac pytest: fix another flake in test_zeroconf_forget.
fundwallet generates a block: if l2 sees one block and not the other, it can
consider the time on the first fundchannel to be one block earlier than expected:

```
2025-05-05T21:05:33.6260600Z E                   TimeoutError: Unable to find "[re.compile('UNUSUAL 0266e4598d1d3c415f572a8488830b60f7e744ed9235eb0b1ba93283b315c03518-chan#1: Forgetting channel: It has been 51 blocks without the funding transaction ')]" in logs.
...
2025-05-05T21:05:33.7179461Z lightningd-2 2025-05-05T20:44:26.141Z UNUSUAL 0266e4598d1d3c415f572a8488830b60f7e744ed9235eb0b1ba93283b315c03518-chan#1: Forgetting channel: It has been 52 blocks without the funding transaction 5a18d113f53df8b205ab679924babde4068f2d1876d34edc43701bf92b8ff13f getting deeply confirmed. We are fundee and can forget channel without loss of funds.
```

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2025-05-06 12:27:53 +09:30
Rusty Russell
2e5b9bf9d3 pytest: fix up feerates for elements.
They're not quite right (more work needed), but disable those checks for now.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2025-05-06 12:27:53 +09:30
Rusty Russell
74e7264d54 bitcoin: make input witness weight calculation explicit.
This is inspired by a patch from @whitslack, which overlapped with this series.
Most importantly, there was only one call to bitcoin_tx_simple_input_weight(),
and it is better to be explicit with that one.

This also changes our funder calculation to assume our own input is taproot,
which it is likely to be given we've defaulted to taproot for outputs for
change addresses since 23.08.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2025-05-06 12:27:53 +09:30
Rusty Russell
c0d68c5c2c pytest: create warning if we grind signature shorter than 71 bytes, don't fail.
One in 256 times, we will grind a signature to 70 bytes (or shorter).  This breaks
our feerate tests.  Unfortunately the grinding is deterministic, so there doesn't
seem to be a way to avoid it.  So we add a log message, and then we skip the
feerate test if it happens.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2025-05-06 12:27:53 +09:30
Rusty Russell
2ee92f1b25 pytest: enhance tests to test anchor and htlc tx feerates match targets.
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2025-05-06 12:27:53 +09:30
Rusty Russell
9af8c64ff4 txprepare: fix all amount when other amounts also specified.
This is legal!  And we actually do this in tests, but we didn't check the psbt
was spendable (the next patch does, indirectly, by testing feerate):

```
        # Discard prep4 and get all funds again
        l1.rpc.txdiscard(prep5['txid'])
        # You can have one which is all, but not two.
        prep5 = l1.rpc.txprepare([{addr: Millisatoshi(amount * 3 * 1000)},
                                  {addr: 'all'}])
        # Feerate should be ~ as we asked for
>       assert normal_feerate_perkw - 1 < feerate_from_psbt(bitcoind, l1, prep5['psbt']) < normal_feerate_perkw + 1
E       AssertionError: assert (7500 - 1) < -1091803.9574935874
```

Changelog-Fixed: JSON-RPC: `txprepare` with `all` as well as one or more non-all amount fields now produces a valid PSBT.
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2025-05-06 12:27:53 +09:30
Rusty Russell
c927666ef1 wallet: implement dev-finalizepsbt for testing feerates.
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2025-05-06 12:27:53 +09:30
Rusty Russell
0f5990b094 anchorspend: fix weight estimation.
Now we've fixed various underlying weight mis-estimation, we can do a few final tweaks and
test that anchors work as intended.

1. We assumed a p2wpkh output, but modern change is p2tr.
2. We handed `2` instead of `1` to bitcoin_tx_core_weight (which doesn't matter, but was weird).
3. Make change calculation clearer.  I'm not sure the previous one was wrong, but it was harder
   to understand.
4. Fix the test and make it clearly test that we are aiming for (and achieving) the right feerate.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
Changelog-Fixed: Protocol: anchors' fees are now much closer to the feerate targets.
2025-05-06 12:27:53 +09:30
Rusty Russell
1d5cb4b49c bitcoin: fix out-by-one-error in bitcoin_tx_input_weight.
We need one byte for the number of witness elements.  Some callers added it themselves,
but it's always needed.  So document and fix the callers.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2025-05-06 12:27:53 +09:30
Rusty Russell
70f05132d9 channeld: be more accurate with the weight of commitment txs.
We didn't add the weight of the two sigs!  The BOLT defines that to be a worst-case 73 byte sig,
but that turns out to be an overestimate (and this is not required for consensus) so we assume
everyone grinds.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2025-05-06 12:27:53 +09:30
Rusty Russell
65a145f1d9 wallet: generalize wallet_utxo_boost.
We use this for anchors, in which case we have a minimum value for
change.  If we don't take this into account, we end up with a lower
feerate once we actually create the tx.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2025-05-06 12:27:53 +09:30
Rusty Russell
a8f75cca28 common: fix utxo_spend_weight to understand how cheap P2TR is.
We previously treated it as a P2WPKH, which is wrong.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
Changelog-Fixed: wallet: fees are much closer to target feerate when doing txprepare/fundchannel.
2025-05-06 12:27:53 +09:30
Rusty Russell
27b98892f7 lightningd: fail too-large txs *before* opening channel.
Due to a bug elsewhere I actually triggered this path, and it
broadcast the tx anyway, *then* closed the channel.  We should abandon
the channel if we can, instead.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2025-05-06 12:27:53 +09:30
Rusty Russell
c0ddfa23cc wallet: make enum wallet_output_type UPPERCASE.
No code change, just following convention.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2025-05-06 12:27:53 +09:30
Rusty Russell
7a276bbe09 common/utxo: use a real type for the UTXO, not a boolean is_p2sh.
To actually evaluate spend cost, we need to know whether it's taproot or not.
Using an enum (rather than making callers examine the script) means we can
ensure all cases are handled.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2025-05-06 12:27:53 +09:30
Rusty Russell
2154289911 hsmd: rename simple_htlc to hsm_htlc, don't gratuitously dynamically allocate.
The renaming makes it clear that it's HSM specific.

And it has no pointers, so we can have an array instead of an array of pointers.

I tested this hadn't accidentally changed the wire format by disabling
version checks and using an old hsmd with the altered daemons and
running the test suite.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2025-05-06 12:27:53 +09:30
Rusty Russell
29c8693b26 hsmd: roll the definition of simple_htlc into the csv.
This is such a simple struct that we can actually define it in csv.
This prevents us from accidentally breaking the ABI in future.

I tested this hadn't accidentally changed the wire format by disabling
version checks and using an old hsmd with the altered daemons and
running the test suite.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2025-05-06 12:27:53 +09:30
Rusty Russell
daf1560eb4 hsmd: make our private utxo type, to ensure binary compatibility.
I'm about to update our utxo type, but Christian spotted that this is
part of the ABI for the hsm.  So make that a private "hsm_utxo" type,
to insulate it from changes.

In particular, the HSM versions only contain the fields that the
hsm cares about, and the wire format is consistent (even though that
*did* include some of those fields, they are now dummies).

In the long term, this should be removed from the ABI: once we
no longer have "close_info" utxos, this information should already be
in the PSBT.

I tested this hadn't accidentally changed the wire format by disabling
version checks and using an old hsmd with the altered daemons and
running the test suite.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2025-05-06 12:27:53 +09:30
Rusty Russell
f992eb1e72 openingd: don't cast existing_htlc array to simple_htlc array.
It's NULL, but the case covered up that it's the wrong type!

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2025-05-06 12:27:53 +09:30
Rusty Russell
8d819d36d5 lightningd: return addrtype when asking wallet_can_spend.
Not just the key index.

Also, remove FIXME: wallet_can_spend is no longer slow with lots of inputs!

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2025-05-06 12:27:53 +09:30
Rusty Russell
8087ab456c lightningd: don't attach an anchor at all if feerate already sufficient.
We're about to fix the feerate calculations in various places, and one
side effect is that we end up trying to add an empty anchor if none is
necessary (and failing, but we log a nasty message about it).

So don't do that, and fix the test which expected it.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2025-05-06 12:27:53 +09:30
Rusty Russell
4ed0435619 pytest: fix block count in test_zeroconf_forget.
We actually need to mine another block, so that lightningd considers both
channels candidates for forgetting (and forgets the older one).

Reported-by: daywalker90
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2025-05-05 12:44:46 -07:00
Rusty Russell
da56a8e657 pytest: don't use wrappers when we need dev arguments.
Pointed out by daywalker90, the introduction of wrappers caused
these tests to break.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2025-05-05 12:44:46 -07:00
Rusty Russell
94a247d982 pyln-testing: fail typecheck gracefully on integer.
We say the offer amount arg can be either an `msat_or_any` or a `currency` string, but technically the order of evaluation is undefined, so it can check the other way, and it should not crash:

```
>       offer = l3.rpc.offer(1000, 'test_pay_blindedpath_nodeaddr')

tests/test_pay.py:5692: 
...
checker = <TypeChecker types={'array', 'bip340sig', 'boolean', 'currency', 'feerate', 'hash', 'hex', 'integer', 'msat', 'msat_or..._all', 'secret', 'short_channel_id', 'short_channel_id_dir', 'signature', 'string', 'txid', 'u16', 'u32', 'u64', 'u8'}>
instance = 1000

    def is_currency(checker, instance):
        """currency including currency code"""
        pattern = re.compile(r'^\d+(\.\d+)?[A-Z][A-Z][A-Z]$')
>       if pattern.match(instance):
E       TypeError: expected string or bytes-like object

```

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2025-05-05 12:44:46 -07:00
daywalker90
459c756040 cln-plugin: trace level logging support
Changelog-None
2025-05-05 09:31:22 -07:00
Jiri Jakes
f8ca160500 doc: Remove mentions of 'helpme' plugin
Plugin 'helpme' has been archived, the change removes all mentions of
it from documentation.

Changelog-None
2025-05-05 13:58:22 +09:30
Lagrang3
47babbf661 askrene: add LOG_TRACE to every rpc entry point
This could be helpful for debugging the interaction of renepay/xpay with
askrene.

Changelog-None

Signed-off-by: Lagrang3 <lagrang3@protonmail.com>
2025-05-02 13:59:13 -07:00
Lagrang3
0de781dc6d renepay: log renepay steps with LOG_TRACE
Previously it was flagged as LOG_DBG, but produces very verbose log
files.

Changelog-None

Signed-off-by: Lagrang3 <lagrang3@protonmail.com>
2025-05-02 13:59:13 -07:00
Lagrang3
e848f1019e startup_regtest: show "trace" events in the logs
Changelog-None

Signed-off-by: Lagrang3 <lagrang3@protonmail.com>
2025-05-02 13:59:13 -07:00
Lagrang3
be6a140777 libplugin: fix LOG_TRACE for plugins
A log event LOG_TRACE submitted by a plugin was being logged as
**BROKEN** by lightningd before this commit.

Changelog-Fixed: plugins can now log events under the LOG_TRACE flag.

Signed-off-by: Lagrang3 <lagrang3@protonmail.com>
2025-05-02 13:59:13 -07:00
21M4TW
3da1bdb368 pyln-client: Adding disableoffer, enableoffer, fetchinvoice, listoffers and offer commands
Changelog-None.
2025-05-02 13:57:04 -07:00
Rusty Russell
1dee02c5e3 pyln-client: reimplement NodeVersion, simply.
This broke my build machine, because lightningd --version was malformed
(I had no tags somehow in that branch).

I dived into the code to figure out what was wrong, and I was horrified.

1. STOP.  Never write this much code.
2. You just need a NodeVersion class.  That's it.  No others.
3. Don't throw away the entire first part if it starts with 'v'.  Just remove the v.
4. Handle untagged versions cleanly.
5. Always fail on invalid strings in the constructor, NOT on the first time you
   use it.

I have rewritten it.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2025-05-02 13:48:02 -07:00
ShahanaFarooqui
40215917ab tests: Lock listclosedchannels sequence 2025-05-02 13:39:33 -07:00
Alex Myers
51219fe374 doc: add poetry run to build instructions
This is required now that poetry shell is not supported

Changelog-None
2025-05-02 13:39:33 -07:00
Alex Myers
52ac01db25 Dockerfile: lock poetry installation to v2.0.1
This avoids the docker image builders breaking with:
ERROR [linux/amd64 builder 15/17] RUN poetry export -o requirements.txt --without-hashes
0.780 pyproject.toml changed significantly since poetry.lock was last generated. Run Resolving dependencies... to fix the lock file.

This occurred when the default installation version changed underneath us.

Changelog-None
2025-05-02 13:39:33 -07:00
Alex Myers
a4e0091565 poetry: update all pyproject.toml files for poetry 2.0.1
and run poetry lock

Changelog-None
2025-05-02 13:39:33 -07:00
Peter Neuroth
ae226cbf7a lsps: Add additional documentation
Adds some additional documentation to the json-rpc v2.0 messages
and error types.

Signed-off-by: Peter Neuroth <pet.v.ne@gmail.com>
2025-05-02 13:34:21 -07:00
Peter Neuroth
cb876b6288 lsps: Add test for Lsps0
Signed-off-by: Peter Neuroth <pet.v.ne@gmail.com>
2025-05-02 13:34:21 -07:00
Peter Neuroth
e879f88eb0 lsps: Add service implementation for LSPS0
Implements the LSPS0 service plugin for core lightning

Changelog-Added: lsps-plugin: lsps0 service support

Signed-off-by: Peter Neuroth <pet.v.ne@gmail.com>
2025-05-02 13:34:21 -07:00
Peter Neuroth
f3f222f39f lsps: Add client implementation of LSPS0
We want a working client to run some integration tests.

Changelog-Added: lsps-plugin: lsps0 client support
2025-05-02 13:34:21 -07:00
Peter Neuroth
4d9ed8e2fb lsps: Implement the transport layer for lsps0
For lsps0 we send JSON-RPC messages via custom messages over the
lightning network. This commit adds a basic implementation based
on custom messages.
2025-05-02 13:34:21 -07:00
Peter Neuroth
68ca86ca4f lsps: Add JSON-RPC V2 server 2025-05-02 13:34:21 -07:00
Peter Neuroth
203621a629 lsps: Implement JSON-RPC V2 client
Adds an async safe JSON-RPC V2 client for a generic transport layer. The
transport layer we will use later on are BOLT8 lightning messages.

Signed-off-by: Peter Neuroth <pet.v.ne@gmail.com>
2025-05-02 13:34:21 -07:00
Peter Neuroth
ea5635c4c8 lsps: Implement JSON-RPC message structure
Signed-off-by: Peter Neuroth <pet.v.ne@gmail.com>
2025-05-02 13:34:21 -07:00
Rusty Russell
a12c02b1d0 pytest: fix race in test_zeroconf_forget
fundwallet() actually mines a block, putting our count out.  If we see
both blocks at once, we will say "52" blocks instead of "51":

```
2025-05-02T05:28:40.5315155Z         have_forgotten = l2.daemon.is_in_log(
2025-05-02T05:28:40.5315650Z             r"UNUSUAL {}-chan#1: Forgetting channel: It has been 51 blocks without the funding transaction ".format(l1.info['id'])
2025-05-02T05:28:40.5316105Z         )
2025-05-02T05:28:40.5316263Z     
2025-05-02T05:28:40.5316417Z         if dopay:
2025-05-02T05:28:40.5316616Z             assert not have_forgotten
2025-05-02T05:28:40.5317056Z             assert set([c['peer_id'] for c in l2.rpc.listpeerchannels()["channels"]]) == set([l1.info['id'], l3.info['id']])
2025-05-02T05:28:40.5317477Z         else:
2025-05-02T05:28:40.5317662Z >           assert have_forgotten
2025-05-02T05:28:40.5317887Z E           assert None
```

```
0266e4598d1d3c415f572a8488830b60f7e744ed9235eb0b1ba93283b315c03518-chan#1: Forgetting channel: It has been 52 blocks without the funding transaction 0bb0579df6b1d983dda49dad47513afc71696c9d5bea3c8b955ba4b76bb053de getting deeply confirmed. We are fundee and can forget channel without loss of funds.
```

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2025-05-02 13:25:11 -07:00
Rusty Russell
5778083cbd CI: disable the doc check for now.
It's not completely stable, which is OK, and we will solve this next release.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2025-05-02 13:25:11 -07:00
Rusty Russell
ad365886e3 libplugin: support LOG_TRACE level logging.
Otherwise it comes out as "**BROKEN**" messages:

```
lightningd-2 2025-05-02T03:51:28.760Z **BROKEN** plugin-chanbackup: Peer storage sent!
lightningd-1 2025-05-02T03:51:28.770Z **BROKEN** plugin-chanbackup: Peer storage sent!
```

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2025-05-02 13:25:11 -07:00
Rusty Russell
f054600723 pytest: fix flake in test_setconfig_access.
We were supposed to put the sqlite db in a different directory, but
the test was wrong!  So occasionally we would crash with:

```
Failed to commit DB transaction: Failed to commit a transaction: disk I/O error
```

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2025-05-02 13:25:11 -07:00
Rusty Russell
fb0f62e402 CI: fix flake in test_penalty_htlc_tx_timeout
Make sure l1 sees the l5 channel!

```
2025-04-29T02:39:42.1086397Z         # now we send two 'sticky' htlcs, l1->l5 + l4->l1
2025-04-29T02:39:42.1086837Z         amt = 10**8 // 2
2025-04-29T02:39:42.1087231Z         sticky_inv_1 = l5.rpc.invoice(amt, '2', 'sticky')
2025-04-29T02:39:42.1087767Z >       route = l1.rpc.getroute(l5.info['id'], amt, 1)['route']
2025-04-29T02:39:42.1088126Z 
2025-04-29T02:39:42.1088279Z tests/test_closing.py:1432: 
...
2025-04-29T02:39:42.1111693Z         elif "error" in resp:
2025-04-29T02:39:42.1111976Z >           raise RpcError(method, payload, resp['error'])
2025-04-29T02:39:42.1113258Z E           pyln.client.lightning.RpcError: RPC call failed: method: getroute, payload: {'id': '032cf15d1ad9c4a08d26eab1918f732d8ef8fdc6abb9640bf3db174372c491304e', 'amount_msat': 50000000, 'riskfactor': 1, 'cltv': 9}, error: {'code': -32602, 'message': '032cf15d1ad9c4a08d26eab1918f732d8ef8fdc6abb9640bf3db174372c491304e: unknown destination node_id (no public channels?)'}
```

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2025-05-02 13:25:11 -07:00
Rusty Russell
099a7ecab6 pytest: fix flake in test_xpay_twohop_bug
CLTV can be one less if l1 hasn't seen block yet:

```
2025-04-24T05:38:12.8587408Z >       l1.daemon.wait_for_log(f'Adding HTLC 0 amount=15002msat cltv={110 + 1 + 100 + 200 + 400}')
2025-04-24T05:38:12.8587715Z 
2025-04-24T05:38:12.8587804Z tests/test_xpay.py:824: 
...
2025-04-24T05:38:12.9889506Z lightningd-1 2025-04-24T05:30:45.255Z DEBUG   022d223620a359a47ff7f7ac447c85c46c923da53389221a0054c11c1e3ca31d59-channeld-chan#1: Adding HTLC 0 amount=15002msat cltv=812 gave CHANNEL_ERR_ADD_OK
```

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2025-05-02 13:25:11 -07:00
Rusty Russell
2c57347033 plugins: wss-proxy should not return invalid JSON if sed does not exist.
We try to do a JSON response if Python is not present, but it assumes sed.  We should cleanly
exit on errors.

Before:

```
$ PATH=/tmp ./plugins/wss-proxy/wss-proxy
Something

./plugins/wss-proxy/wss-proxy: 12: sed: not found
{"jsonrpc":"2.0","id":,"result":{"disable":"No python3 binary found"}}
```

After:

```
$ PATH=/tmp ./plugins/wss-proxy/wss-proxy
something

./plugins/wss-proxy/wss-proxy: 12: sed: not found
```

Reported-by: Christian Decker
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2025-05-02 13:23:41 -07:00
daywalker90
eef3bfe561 cln-rpc: Implemented the From<u64> trait for ShortChannelId
Changelog-None
2025-05-02 15:04:29 +02:00
Rusty Russell
8d54a82d2d pytest: fix CI hang.
This finally happened on my local build machine, so I tracked it down using
py-spy, `apt-get install python3-dbg` and `py-local`.

Turns out the dev-memleak command was hanging, and the processes were stuck in
SIGSTOP.  There are only two places we send that, and sure enough, this was
the test which was running at the time.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2025-05-02 12:15:18 +09:30
ShahanaFarooqui
c35c06c52e doc: Update May release dates 2025-05-01 19:34:29 -07:00
Aditya Sharma
9a5ef91d62 Change LOG_INFORM to LOG_TRACE in chanbackup
plugin_log inside after_send_scb_single was logging after sending peer storage
to each peer which could lead to spam in logs for big nodes, hence we should reduce
the log level to log_trace for it.

Changelog-Fixed: Suppress logs from chanbackup
2025-05-01 19:24:51 -07:00
daywalker90
8a56ccd2de docs: add RUST_PROFILE to installation steps
Changelog-None
2025-04-30 13:31:33 -07:00
Se7enZ
284e38e692 doc: minor typos and standarizations to inline documentaion.
Fixed typos and standardized English spelling of "neighbor" to match
the variable names.

Changelog-None
2025-04-29 09:40:15 -07:00
Rusty Russell
43b09e73f7 lightningd: respond with channel_reestablish if contacted about long-closed channels.
This may be useful for their recovery, though they should see the spend onchain.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
Changelog-Added: Protocol: We now reply to `channel_reestablish` even on long-closed channels.
2025-04-29 13:31:23 +09:30
Rusty Russell
c9f34a64e3 lightningd: save shachain for closed channels.
We'll need this to send reestablish, and it is only small (max 47 sha256 per channel).

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2025-04-29 13:31:23 +09:30
Rusty Russell
6e4fb1eb56 channeld: remove never-used "reestablish_only" option.
This was always false.  peer_start_channeld was called in various places
with the argument "NULL" instead of "false", which unfortunately compilers
didn't complain about :(

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2025-04-29 13:31:23 +09:30
Rusty Russell
1fe5644bf2 lightningd: keep closed channels in memory.
They're small, and this will allow us to efficiently respond to reestablish on them.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2025-04-29 13:31:23 +09:30
Rusty Russell
3b80a81031 lightningd: allow up to 100 "slow open" channels before forgetting them.
Michael of Boltz told me this long ago, that when fees spiked some of their clients' opens got stuck.  After two weeks their node forgot them, and when fees came back down the opens still failed.  Unfortunately, I can't see an issue for this!

We can give some grace: we don't want to waste too many resources, but 100 channels is nothing.

The test needs to be adjusted to have *two* slow open channels, now.

Changelog-Changed: Protocol: we won't forget still-opening channels after 2016 blocks, unless there are more than 100.
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2025-04-29 13:31:23 +09:30
Rusty Russell
baf3c831dd lightningd: neaten delete_channel.
Use convenience variables.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2025-04-29 13:31:23 +09:30
Rusty Russell
e8aac7e4a9 lightningd: delete all trace of nonexistent channels.
We're going to start loading them into memory for nicer responses if
people try to reestablish closed channels, but we don't care about ones
which were never actually opened.  We could add a new state, but easier
to simply remove them.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2025-04-29 13:31:23 +09:30
Rusty Russell
98619a03f2 wallet: fix erroneous allocation of db_col_optional_scid.
We are supposed to allocate of the ctx we're passed, not tmpctx.

Doesn't matter for now, because we don't use this result with anything which outlives tmpctx,
but we're going to:

```
==47574==ERROR: AddressSanitizer: heap-use-after-free on address 0x6040005a8f38 at pc 0x55d3c584d252 bp 0x7ffddfb1b090 sp 0x7ffddfb1b088
READ of size 8 at 0x6040005a8f38 thread T0
    #0 0x55d3c584d251 in json_add_closed_channel /home/runner/work/lightning/lightning/lightningd/closed_channel.c:27:3
    #1 0x55d3c584ca5a in json_listclosedchannels /home/runner/work/lightning/lightning/lightningd/closed_channel.c:118:3
    #2 0x55d3c58c0cbe in command_exec /home/runner/work/lightning/lightning/lightningd/jsonrpc.c:808:8
```

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2025-04-29 13:31:23 +09:30
Rusty Russell
6bf36915fd lightningd: support index/start/end pagination for listhtlcs.
Changelog-Added: JSON-RPC: `listhtlcs` supports `index`, `start` and `end` parameters for pagination support.
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2025-04-29 09:38:20 +09:30
Rusty Russell
7ba6263c48 lightningd: add created_index and updated_index to listhtlcs.
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
Changelog-Added: JSON-RPC: `listhtlcs` has `created_index` and `updated_index` fields.
2025-04-29 09:38:20 +09:30
Rusty Russell
07c495e7fb lightningd: keep indexes updated for channel_htlcs table (aka listhtlcs).
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2025-04-29 09:38:20 +09:30
Rusty Russell
9636553c16 lightningd: wait interface for htlcs indexes.
Note that documentation says invoice expiries can batch, but that's no
longer true, so delete it.  Usually, we miss a number because the
change is too fast.

This adds the wait interface, but it doesn't actually fire until the next
commit, which wires it into the db code.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
Changelog-Added: JSON-RPC: `wait` now supports the `htlcs` (`listhtlcs`) subsystem.
2025-04-29 09:38:20 +09:30
Rusty Russell
186a9383da wallet: add updated_index to channel_htlcs table.
This prepares us for doing listhtlcs pagination.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2025-04-29 09:38:20 +09:30
Rusty Russell
e7315ff6b3 lightningd: allow a more general wait_index increase.
We're not going to increment one at a time for bulk deletion of htlcs
when a channel closes.  There could be millions of HTLCs!

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2025-04-29 09:38:20 +09:30
Rusty Russell
db104aae92 lightningd: improve wait API by making details fields per-subsystem.
It makes the schema simpler, and indeed, expressable by GRPC.

Changelog-Added: JSON-RPC: `wait` now has separate `invoices`, `forwards` and `sendpays` objects for each subsystem.
Changelog-Deprecated: JSON-RPC: `wait` reply `details` object: use subsytem specific object instead.
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2025-04-29 09:38:20 +09:30
Rusty Russell
f7f5696f94 wallet: fix test calls to wallet_htlc_update.
The last argument is a pointer, but we were handing `false`.  Which, for
terrible historic reasons, gets treated as NULL.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2025-04-29 09:38:20 +09:30
Rusty Russell
b15023a5f8 Makefile: remove doc/schemas/lightning-sql.json during obsclean.
Otherwise it can get included in contrib/msggen/msggen/schema.json!

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2025-04-29 09:38:20 +09:30
Rusty Russell
8974375de8 lightningd: add short_channel_id option to listpeerchannels.
Requested-by: @whitslack
Closes: https://github.com/ElementsProject/lightning/issues/8233
Changelog-Added: JSON-RPC: `listpeerchannels` now has a `short_channel_id` parameter for just listing a specific channel.
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2025-04-28 14:13:12 +09:30
Rusty Russell
5a3943f2e0 bkpr: fix unittest when HAVE_USDT=1
```
pseudorand_u64 called!
Aborted (core dumped)
make: *** [Makefile:786: unittest/plugins/bkpr/test/run-bkpr_db] Error 134
```

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2025-04-24 17:34:12 +09:30
Rusty Russell
8cc86f3d88 trace: prevent memleak report.
notleak() doesn't work for lightningd since the first span is created before
memleak (or anything else!) is initialized, so we have to mark it manually.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2025-04-24 17:34:12 +09:30
Rusty Russell
3f136ef42d trace: don't mess up pointers when we reallocate.
It's convenient to have pointers, but we have to do fixups.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2025-04-24 17:34:12 +09:30
Rusty Russell
0c0345a9ac CI: enable tracing so we test that code.
We have a crash right now, which passed CI!

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2025-04-24 17:34:12 +09:30
Rusty Russell
55f870e963 trace: double allocation if we run out.
This doesn't happen very often, but can with autoclean.

However, we rarely traverse to the end, since we always expect to find
what we're looking for, and we fill from the front.  So even a large
array (unless it's used) is fine.

Subtle: when we injected a parent, we used "active_spans" as the (arbitrary)
key.  That can now change with reallocation, and so if that memory were reused
we could have a key clash.  So we use "&active_spans" which doesn't change.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2025-04-23 13:45:18 +09:30
Rusty Russell
858e3b074f common: remove unnecessary parent_id and remote fields.
We don't ever actually close the remote span (we don't have its key,
after all), and we keep a pointer to the parent.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2025-04-23 13:45:18 +09:30
Rusty Russell
6a8e586ea8 trace: don't use randombytes_buf(), use pseudorand.
This is much faster to give 64 bits of data, and we don't need
cryptographic randomness.

This brings us back to 413ns per trace.

Before:
	real	0m5.819000-6.472000(6.2064+/-0.26)s
	user	0m3.779000-4.101000(3.956+/-0.12)s
	sys	0m2.040000-2.431000(2.2496+/-0.15)s

After:
	real	0m3.981000-4.247000(4.1276+/-0.11)s
	user	0m3.979000-4.245000(4.126+/-0.11)s
	sys	0m0.000000-0.002000(0.001+/-0.00063)s

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
Changelog-Fixed: lightingd: trimmed overhead of tracing infrastructure.
2025-04-23 13:45:18 +09:30
Rusty Russell
b4dcf4e55d trace: use a static buffer instead of tal_fmt().
There's an EBPF limit anyway, so stick with a 512-byte buffer.

This brings us back to 621ns per trace:

Before:
	real	0m13.441000-14.592000(14.2686+/-0.43)s
	user	0m11.265000-12.289000(11.9626+/-0.37)s
	sys	0m2.175000-2.381000(2.3048+/-0.072)s

After:
	real	0m5.819000-6.472000(6.2064+/-0.26)s
	user	0m3.779000-4.101000(3.956+/-0.12)s
	sys	0m2.040000-2.431000(2.2496+/-0.15)s

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2025-04-23 13:45:18 +09:30
Rusty Russell
3973c35013 trace: we only ever add two tags, so use a static array.
Avoids allocations.  Also assume that name and value parameters
outlive the trace span, so don't copy.

Before:
	real	0m16.421000-18.407000(17.8128+/-0.72)s
	user	0m14.242000-16.041000(15.5382+/-0.67)s
	sys	0m2.179000-2.363000(2.273+/-0.061)s

After:
	real	0m13.441000-14.592000(14.2686+/-0.43)s
	user	0m11.265000-12.289000(11.9626+/-0.37)s
	sys	0m2.175000-2.381000(2.3048+/-0.072)s

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2025-04-23 13:45:18 +09:30
Rusty Russell
cdb74434f2 trace: don't copy strings where we don't need to.
1. trace_span_start() is always called with a string literal, so
   no copy needed (and we can use a macro to enforce this).
2. trace_span_tag() name and value are always longer-lived than
   the span, so no need to copy these either.

Before:
	real	0m18.524000-19.100000(18.7674+/-0.21)s
	user	0m16.171000-16.833000(16.424+/-0.26)s
	sys	0m2.259000-2.400000(2.337+/-0.059)s

After:
	real	0m16.421000-18.407000(17.8128+/-0.72)s
	user	0m14.242000-16.041000(15.5382+/-0.67)s
	sys	0m2.179000-2.363000(2.273+/-0.061)s

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2025-04-23 13:45:18 +09:30
Rusty Russell
e951155002 trace: fix parent handling (and test it!).
Testing parenting handling revealed several issues:

1. By calling "trace_span_start" when CLN_TRACEPARENT is set produces a bogus
   entry, for which the span_id is overwritten so we never end it.
2. We don't need to close the remote parent when we close the first child: in
   fact, this causes the remaining traces to be detached from the parent!
3. Suspension should return current to the parent, not to NULL.

Now the traces balance as we expect.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2025-04-23 13:45:18 +09:30
Rusty Russell
924f28adcb pytest: add test hooks so we can test tracing.
Suggested-by: Christian Decker
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2025-04-23 13:45:18 +09:30
Rusty Russell
c69a636fef trace: track suspensions, check they match.
I added this debugging because the next test revealed a mismatch, so
I wanted to see where it was happening.

The comment in lightningd suggests it's possible, but I can't see any
code which suspends in the lightningd io_loop, so I cannot see how
this is triggered.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2025-04-23 13:45:18 +09:30
Rusty Russell
f5f87255c1 common/test/run-trace: increase iterations for trivial benchmarking.
With an average runtime of 18.7674, this implies 1876ns
per trace, which is far in excess of the 370ns claimed in
doc/developers-guide/tracing-cln-performance.md.

We also add a tag in there, so we measure that!

Results on my laptop:
	real	0m18.524000-19.100000(18.7674+/-0.21)s
	user	0m16.171000-16.833000(16.424+/-0.26)s
	sys	0m2.259000-2.400000(2.337+/-0.059)s

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2025-04-23 13:45:18 +09:30
Vincenzo Palazzo
7198fec853 db: replace UPDATE FROM syntax for SQLite compat
Introduced the use of UPDATE FROM syntax in SQLite queries,
which is not supported in versions prior to 3.33.0.

This causes issues on systems with older SQLite versions,
 as reported in issue #8231. Rewrite the query in
 migrate_convert_old_channel_keyidx() to use a subquery
 with IN clause instead of UPDATE FROM, ensuring compatibility with
 older SQLite versions.

Changelog-Fixed: db: replace UPDATE FROM syntax for SQLite compat
Fixes 68f3649d6b
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Signed-off-by: Vincenzo Palazzo <vincenzopalazzodev@gmail.com>
2025-04-23 09:53:15 +09:30
Rusty Russell
675ac14986 CI: Install protobuf on FreeBSD
```
cargo build --quiet --example cln-plugin-startup
  error: failed to run custom build command for `cln-grpc v0.4.0 (/home/runner/work/lightning/lightning/cln-grpc)`

  Caused by:
    process didn't exit successfully: `/home/runner/work/lightning/lightning/target/debug/build/cln-grpc-1c0900b8d6f448d4/build-script-build` (exit status: 101)
    --- stdout
    cargo:rerun-if-changed=proto/node.proto
    cargo:rerun-if-changed=proto

    --- stderr

    thread 'main' panicked at cln-grpc/build.rs:7:10:
    called `Result::unwrap()` on an `Err` value: Custom { kind: NotFound, error: "Could not find `protoc`. If `protoc` is installed, try setting the `PROTOC` environment variable to the path of the `protoc` binary. Try installing `protobuf-compiler` or `protobuf` using your package manager. It is also available at https://github.com/protocolbuffers/protobuf/releases  For more information: https://docs.rs/prost-build/#sourcing-protoc" }
    note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
  gmake: *** [cln-rpc/Makefile:15: target/debug/examples/cln-plugin-startup] Error 101
```

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2025-04-23 09:21:43 +09:30
Rusty Russell
fe3ee1e4e6 CI: mark external subdirs safe for FreeBSD build
```
fatal: detected dubious ownership in repository at '/home/runner/work/lightning/lightning/external/libwally-core'
  To add an exception for this directory, call:

  	git config --global --add safe.directory /home/runner/work/lightning/lightning/external/libwally-core
  Reinitializing submodules src/secp256k1 ...
  fatal: detected dubious ownership in repository at '/home/runner/work/lightning/lightning/external/libwally-core'
  To add an exception for this directory, call:

  	git config --global --add safe.directory /home/runner/work/lightning/lightning/external/libwally-core
  fatal: detected dubious ownership in repository at '/home/runner/work/lightning/lightning/external/libwally-core'
  To add an exception for this directory, call:

  	git config --global --add safe.directory /home/runner/work/lightning/lightning/external/libwally-core
  gmake: *** [external/Makefile:65: submodcheck] Error 128
```

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2025-04-23 09:21:43 +09:30
Rusty Russell
afe911173a CI: install jq for FreeBSD build.
```
  checking for jq... not found
  *** We need jq!
```

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2025-04-23 09:21:43 +09:30
Rusty Russell
d201bdacea ci: install pkg-config for FreeBSD.
```
      | -- Found Python: /tmp/tmpyjjd1wyq/.venv/bin/python (found suitable version "3.11.11", minimum required is "3") found components: Interpreter Development.Module Development.SABIModule
      | CMake Error at /tmp/tmpyjjd1wyq/.venv/lib/python3.11/site-packages/cmake/data/share/cmake-4.0/Modules/FindPackageHandleStandardArgs.cmake:227 (message):
      |   Could NOT find PkgConfig (missing: PKG_CONFIG_EXECUTABLE)
      | Call Stack (most recent call first):
      |   /tmp/tmpyjjd1wyq/.venv/lib/python3.11/site-packages/cmake/data/share/cmake-4.0/Modules/FindPackageHandleStandardArgs.cmake:591 (_FPHSA_FAILURE_MESSAGE)
      |   /tmp/tmpyjjd1wyq/.venv/lib/python3.11/site-packages/cmake/data/share/cmake-4.0/Modules/FindPkgConfig.cmake:110 (find_package_handle_standard_args)
      |   CMakeLists.txt:35 (find_package)
      |
      |
      | -- Configuring incomplete, errors occurred!
      | Traceback (most recent call last):
      |   File "/root/.local/lib/python3.10/site-packages/pyproject_hooks/_in_process/_in_process.py", line 389, in <module>
      |     main()
      |   File "/root/.local/lib/python3.10/site-packages/pyproject_hooks/_in_process/_in_process.py", line 373, in main
      |     json_out["return_val"] = hook(**hook_input["kwargs"])
      |                              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
      |   File "/root/.local/lib/python3.10/site-packages/pyproject_hooks/_in_process/_in_process.py", line 280, in build_wheel
      |     return _build_backend().build_wheel(
      |            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
      |   File "/tmp/tmpyjjd1wyq/.venv/lib/python3.11/site-packages/hatchling/build.py", line 58, in build_wheel
      |     return os.path.basename(next(builder.build(directory=wheel_directory, versions=['standard'])))
      |                             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
      |   File "/tmp/tmpyjjd1wyq/.venv/lib/python3.11/site-packages/hatchling/builders/plugin/interface.py", line 147, in build
      |     build_hook.initialize(version, build_data)
      |   File "/tmp/tmpyjjd1wyq/.venv/lib/python3.11/site-packages/scikit_build_core/hatch/plugin.py", line 125, in initialize
      |     self._initialize(build_data=build_data)
      |   File "/tmp/tmpyjjd1wyq/.venv/lib/python3.11/site-packages/scikit_build_core/hatch/plugin.py", line 228, in _initialize
      |     builder.configure(
      |   File "/tmp/tmpyjjd1wyq/.venv/lib/python3.11/site-packages/scikit_build_core/builder/builder.py", line 283, in configure
      |     self.config.configure(
      |   File "/tmp/tmpyjjd1wyq/.venv/lib/python3.11/site-packages/scikit_build_core/cmake.py", line 254, in configure
      |     raise FailedLiveProcessError(msg) from None
      | scikit_build_core.errors.FailedLiveProcessError: CMake configuration failed

  Note: This error originates from the build backend, and is likely not a problem with poetry but one of the following issues with coincurve (20.0.0)

    - not supporting PEP 517 builds
    - not specifying PEP 517 build requirements correctly
    - the build requirements are incompatible with your operating system or Python version
    - the build requirements are missing system dependencies (eg: compilers, libraries, headers).

  You can verify this by running pip wheel --no-cache-dir --use-pep517 "coincurve (==20.0.0)".
```

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2025-04-23 09:21:43 +09:30
Rusty Russell
e320c21948 CI: Try to ensure that poetry can find rust to build packages.
No, really:

```
IsolatedBuildInstallError
    Failed to install maturin>=1.2,<2.0.

    Output:
    Updating dependencies
    Resolving dependencies...

    Package operations: 1 install, 0 updates, 0 removals

      - Installing maturin (1.8.3)

    PEP517 build of a dependency failed

    Backend subprocess exited when trying to invoke build_wheel

        | Command '['/tmp/tmp0qxx7olq/.venv/bin/python', '/root/.local/lib/python3.10/site-packages/pyproject_hooks/_in_process/_in_process.py', 'build_wheel', '/tmp/tmpu1wwwrff']' returned non-zero exit status 1.
        |
        | /tmp/tmp0qxx7olq/.venv/lib/python3.11/site-packages/setuptools/config/_apply_pyprojecttoml.py:82: SetuptoolsDeprecationWarning: `project.license` as a TOML table is deprecated
        | !!
        |
        |         ********************************************************************************
        |         Please use a simple string containing a SPDX expression for `project.license`. You can also use `project.license-files`. (Both options available on setuptools>=77.0.0).
        |
        |         By 2026-Feb-18, you need to update your project and remove deprecated calls
        |         or your builds will no longer be supported.
        |
        |         See https://packaging.python.org/en/latest/guides/writing-pyproject-toml/#license for details.
        |         ********************************************************************************
        |
        | !!
        |   corresp(dist, value, root_dir)
        | running bdist_wheel
        | running build
        | running build_py
        | creating build/lib.freebsd-14.2-RELEASE-amd64-cpython-311/maturin
        | copying maturin/__init__.py -> build/lib.freebsd-14.2-RELEASE-amd64-cpython-311/maturin
        | copying maturin/__main__.py -> build/lib.freebsd-14.2-RELEASE-amd64-cpython-311/maturin
        | running egg_info
        | writing maturin.egg-info/PKG-INFO
        | writing dependency_links to maturin.egg-info/dependency_links.txt
        | writing requirements to maturin.egg-info/requires.txt
        | writing top-level names to maturin.egg-info/top_level.txt
        | reading manifest file 'maturin.egg-info/SOURCES.txt'
        | reading manifest template 'MANIFEST.in'
        | warning: no files found matching '*.json' under directory 'src/python_interpreter'
        | writing manifest file 'maturin.egg-info/SOURCES.txt'
        | running build_ext
        | running build_rust
        | error: can't find Rust compiler
```

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2025-04-23 09:21:43 +09:30
Rusty Russell
0aa0efc989 CI: fix FreeBSD to use poetry to build.
Did this ever work?

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2025-04-23 09:21:43 +09:30
Rusty Russell
e63dca5078 CI: don't try to copy files out of FreeBSD VM
```
...
  skipping non-regular file "lightning/lightning/ccan/ccan/short_types/LICENSE"
  skipping non-regular file "lightning/lightning/ccan/ccan/str/LICENSE"
  skipping non-regular file "lightning/lightning/ccan/ccan/str/base32/LICENSE"
  skipping non-regular file "lightning/lightning/ccan/ccan/str/hex/LICENSE"
  skipping non-regular file "lightning/lightning/ccan/ccan/strmap/LICENSE"
  skipping non-regular file "lightning/lightning/ccan/ccan/structeq/LICENSE"
  skipping non-regular file "lightning/lightning/ccan/ccan/take/LICENSE"
  skipping non-regular file "lightning/lightning/ccan/ccan/tal/LICENSE"
  skipping non-regular file "lightning/lightning/ccan/ccan/tal/grab_file/LICENSE"
  skipping non-regular file "lightning/lightning/ccan/ccan/tal/link/LICENSE"
  skipping non-regular file "lightning/lightning/ccan/ccan/tal/path/LICENSE"
  skipping non-regular file "lightning/lightning/ccan/ccan/tal/str/LICENSE"
  skipping non-regular file "lightning/lightning/ccan/ccan/tcon/LICENSE"
  skipping non-regular file "lightning/lightning/ccan/ccan/time/LICENSE"
  skipping non-regular file "lightning/lightning/ccan/ccan/timer/LICENSE"
  skipping non-regular file "lightning/lightning/ccan/ccan/typesafe_cb/LICENSE"
  skipping non-regular file "lightning/lightning/ccan/ccan/utf8/LICENSE"
  skipping non-regular file "lightning/lightning/doc/CHANGELOG.md"
  skipping non-regular file "lightning/lightning/doc/LICENSE.md"

  sent 583 bytes  received 1,319,490 bytes  880,048.67 bytes/sec
  total size is 62,270,071  speedup is 47.17
Error: The process '/usr/bin/bash' failed with exit code 1
```

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2025-04-23 09:21:43 +09:30
Rusty Russell
730697ef07 CI: don't download bitcoind for FreeBSD build.
It didn't work, and it was downloading the Linux binary anyway!

```
  2025-04-11 02:37:12 (1.61 MB/s) - ‘bitcoin-27.1-x86_64-linux-gnu.tar.gz’ saved [48920073/48920073]

  tar: Error opening archive: Failed to open 'bitcoin-27.1-x86_64-linux-gnu.tar.bz2'
```

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2025-04-23 09:21:43 +09:30
Rusty Russell
36cbdae608 CI: update freebsd test to python 3.10.
```
 12 MiB to be downloaded.
  [1/1] Fetching pkg-2.1.0.pkg: .......... done
  Checking integrity... done (0 conflicting)
  [1/1] Upgrading pkg from 1.21.3 to 2.1.0...
  [1/1] Extracting pkg-2.1.0: .......... done
  Updating FreeBSD repository catalogue...
  FreeBSD repository is up to date.
  All repositories are up to date.
  pkg: No packages available to install matching 'python38' have been found in the repositories
  Error: The process '/usr/bin/bash' failed with exit code 1
```

Changelog-None: CI only
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2025-04-23 09:21:43 +09:30
Peter Neuroth
030a114781 rs: Export NotificationStream
Services that want to wrap the server implementation will need
access to the `NotificationStream` struct in order to pass
the stream through.

Changelog-Added: `cln-grpc` Exposed NotificationStream in the server module

Signed-off-by: Peter Neuroth <pet.v.ne@gmail.com>
2025-04-21 18:33:34 +02:00
Peter Neuroth
b8c39bb12d rs: Refine lib.rs checking for server flag
The `cfg-if` macro allows us to organise feature flag related
exports in a more concise way.

Signed-off-by: Peter Neuroth <pet.v.ne@gmail.com>
2025-04-21 18:33:34 +02:00
Matt Whitlock
e0ded492bd Makefile: also include cln-grpc/Makefile
Changelog-None
2025-04-21 18:26:35 +02:00
Matt Whitlock
0a07da1d8b cln-rpc/Makefile: fix typo CLN_RPC_GEN_ALL=>CLN_RPC_GENALL
Changelog-None
2025-04-21 18:26:35 +02:00
Lakshya Singh
e4a16800ab fix: workaround for macOS AF_UNIX path error
@pytest.mark.openchannel('v1')
    @pytest.mark.openchannel('v2')
    def test_pay(node_factory):
>       l1, l2 = node_factory.line_graph(2)
...
FAILED tests/test_pay.py::test_pay - OSError: AF_UNIX path too long

Changelog-None: symlink the socket to a tempfile which has a shorter path

Signed-off-by: Lakshya Singh <lakshay.singh1108@gmail.com>
2025-04-21 11:45:15 +02:00
Rusty Russell
139d21173b pytest: fix test_recover_plugin flake
It can try to reconnect while we're explicitly connecting:

```
2025-04-15T03:40:53.9184103Z >       l2.rpc.connect(l1.info['id'], 'localhost', l1.port)
2025-04-15T03:40:53.9184311Z 
2025-04-15T03:40:53.9184401Z tests/test_misc.py:3078:
...
2025-04-15T03:40:53.9206302Z >           raise RpcError(method, payload, resp['error'])
2025-04-15T03:40:53.9207225Z E           pyln.client.lightning.RpcError: RPC call failed: method: connect, payload: {'id': '0266e4598d1d3c415f572a8488830b60f7e744ed9235eb0b1ba93283b315c03518', 'host': 'localhost', 'port': 45219}, error: {'code': 402, 'message': 'disconnected during connection'}
```

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2025-04-16 08:02:14 +09:30
Rusty Russell
afa8875c8a pytest: fix race in test_renepay where we didn't wait for all channels.
get_channel_scid() returns the *first* channel, and we want all the channels.
So they may not actually be all visible in gossip.

```
    @unittest.skipIf(TEST_NETWORK == 'liquid-regtest', "broken for some reason")
    def test_hardmpp2(node_factory, bitcoind):
        """Credits to @daywalker90 for this test case."""
        opts = {"disable-mpp": None, "fee-base": 0, "fee-per-satoshi": 10}
        l1, l2, l3 = node_factory.get_nodes(3, opts=opts)
        start_channels(
            [
                (l1, l2, 100_000),
                (l1, l2, 200_000),
                (l1, l2, 300_000),
                (l1, l2, 400_000),
                (l2, l3, 100_000),
                (l2, l3, 200_000),
                (l2, l3, 300_000),
                (l2, l3, 600_000),
            ]
        )
        # FIXME: changing the last channel from 600k to 400k will fail the test due
        # to l2 not accepting to forward any amount above 200k with error:
        # CHANNEL_ERR_CHANNEL_CAPACITY_EXCEEDED, still investigating
        inv = l3.rpc.invoice("800000sat", "inv", "description")
>       l1.rpc.call("renepay", {"invstring": inv["bolt11"]})

tests/test_renepay.py:797: 
...
        elif "error" in resp:
>           raise RpcError(method, payload, resp['error'])
E           pyln.client.lightning.RpcError: RPC call failed: method: renepay, payload: {'invstring': 'lnbcrt8m1pnl3zfksp54n6vhkrcj0nkn2uqhf232v62539048u2ree4g9ssytm47gasgctspp58twj5xf4h57s4h0rhy55p5q6nry36glummjexsf4lc446je7y27qdqjv3jhxcmjd9c8g6t0dcxqyjw5qcqp9rzjqgkjyd3q5dv6gllh77kygly9c3kfy0d9xwyjyxsq2nq3c83u5vw4jqqqvuqqqzqqqqqqqqqqqqqqqzsqqcrzjqgkjyd3q5dv6gllh77kygly9c3kfy0d9xwyjyxsq2nq3c83u5vw4jqqqvuqqqpcqqqqqqqqqqqqqqzsqqcrzjqgkjyd3q5dv6gllh77kygly9c3kfy0d9xwyjyxsq2nq3c83u5vw4jqqqvuqqqqgqqqqqqqqqqqqqqzsqqcrzjqgkjyd3q5dv6gllh77kygly9c3kfy0d9xwyjyxsq2nq3c83u5vw4jqqqvuqqqpqqqqqqqqqqqqqqqzsqqc9qxpqysgqtgxcneu0u7xvetgh2kqmey86jssweneat5vx3fppuaphl9v9jweqa2ymczg9klau9jmsm6pm7m3cd28pggp7avuukjqxg63wy2vuvtcpggz4vt'}, error: {'code': 205, 'message': "minflow couldn't find a feasible flow: failed to find a feasible flow: find_admissible_path failed"}
```

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2025-04-16 08:02:14 +09:30
Matt Morehouse
2811614c37 fuzz: don't fail when fuzzer generates valid Act 1 or 2 packets
The handshake targets were based on a false premise: that it is
impossible for any fuzzer to generate valid Act 1 or 2 packets. Niklas
Gogge proved this premise incorrect using AFL++ with the CMPLOG feature,
which enabled AFL++ to generate such valid packets.

We modify the targets to allow the scenario where the fuzzer finds these
valid packets and add the inputs AFL++ found to the corpus.
2025-04-15 19:53:47 +09:30
Matt Morehouse
2b5140fbcd fuzz: don't fail when fuzzer generates valid MAC
The cryptofuzz target was based on a false premise: that it is
impossible for any fuzzer to generate a valid ciphertext+MAC for the
decrypt function. Niklas Gogge proved this premise incorrect using AFL++
with the CMPLOG feature, which enabled AFL++ to generate such valid
messages.

We remove the assertions requiring decryption to fail and add the inputs
AFL++ found to the corpus.
2025-04-15 19:53:47 +09:30
ShahanaFarooqui
9da6487246 github: Remove prefix from docs and actions
Changelog-Changed: Removed lightning- prefix from schemas/.json and doc/.md files.
2025-04-15 15:17:14 +09:30
ShahanaFarooqui
bf3783c6d2 tests: removed lightning- prefix from autogenerate example 2025-04-15 15:17:14 +09:30
ShahanaFarooqui
2a8cc352f7 plugins: Updated Makefile for SQL plugin 2025-04-15 15:17:14 +09:30
ShahanaFarooqui
2d703fce8e tools: Removed lightning- for schema filename before generating markdowns 2025-04-15 15:17:14 +09:30
ShahanaFarooqui
23364cc812 make: Updated Make commands 2025-04-15 15:17:14 +09:30
ShahanaFarooqui
ad6a599d51 schemas: remove lightning- prefix from filename
This commit will fail in `make` due to unchanged scripts. They will be added in the next commit.
2025-04-15 15:17:14 +09:30
Erick Cestari
d7319795b4 common/bolt11: enforce minimum witness program length for fallback addresses
BIP-141 specifies that a witness program must be between 2 and 40 bytes in
length. In our fallback address parsing, we were already checking the upper
bound, but missing the lower bound check. This commit adds validation to
ensure fallback address witness programs are at least 2 bytes long, bringing
our implementation in line with the spec and other implementations like
rust-lightning.

Changelog-Fixed: Enforced minimum witness program length of 2 bytes for
fallback addresses to comply with BIP-141 and prevent invalid decodings.
2025-04-15 10:41:33 +09:30
Chris Guida
d3c7d2c419 docs: Update install docs for v25.02
Also removes usage of pip due to this error that crops up on newer
versions of Ubuntu:

```
error: externally-managed-environment

× This environment is externally managed
╰─> To install Python packages system-wide, try apt install
    python3-xyz, where xyz is the package you are trying to
    install.

    If you wish to install a non-Debian-packaged Python package,
    create a virtual environment using python3 -m venv path/to/venv.
    Then use path/to/venv/bin/python and path/to/venv/bin/pip. Make
    sure you have python3-full installed.

    If you wish to install a non-Debian packaged Python application,
    it may be easiest to use pipx install xyz, which will manage a
    virtual environment for you. Make sure you have pipx installed.

    See /usr/share/doc/python3.12/README.venv for more information.

note: If you believe this is a mistake, please contact your Python installation or OS distribution provider. You can override this, at the risk of breaking your Python installation or OS, by passing --break-system-packages.
hint: See PEP 668 for the detailed specification.
```

I've been recommending installing Poetry from the official
installer for the past several months and it always works.

Changelog-None
2025-04-08 20:47:49 -05:00
Zen
7e831adadf doc: updating rust details 2025-04-04 22:34:33 -07:00
ShahanaFarooqui
260d62482b ci: Checkout with fresh tags in case the old tag reference is corrupted
The workflow fails to trigger manually after recreating the release tag. It should support re-running even if the tag was previously deleted and recreated.

Changelog-None.
2025-04-04 17:04:22 -05:00
ShahanaFarooqui
d5da3c924b Update Release Dates for May 2025
Changelog-None.
2025-04-04 12:34:18 -07:00
Rusty Russell
90b5f04db9 wallet: don't debug spam every output script as we rescan blocks.
This was left over from debugging!

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2025-04-04 09:04:43 -05:00
daywalker90
deae922cd0 make: remove old clnrest directory
Changelog-None
2025-04-03 13:36:18 -05:00
Rusty Russell
2e6ad3ffc8 trace: handle key being freed while suspended.
This happens with autoclean, which does a datastore request then frees
the parent command without waiting for a response (see clean_finished).

This leaks a trace, and causes a crash if the pointer is later reused.

My solution is to create a trace variant which declares the trace key
to be a tal ptr and then we can clean up in the destructor if this happens.
This fixes the issue for me.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
Changelog-Fixed: autoclean: fixed occasional crash when tracepoints compiled in.
2025-04-03 08:27:27 -05:00
Rusty Russell
7c6270d051 lightningd: rescan for missing p2wkph for closed channels.
This can happen with 24.11 and later.  We scan back to exposed channel
opens, or that release.

The BROKEN log messages cause some tests to fail, so we fix those.

Fixes: https://github.com/ElementsProject/lightning/issues/8169
Changelog-Fixed: wallet: rescan for missing close outputs (can happen if peer doesn't support option_shutdown_anysegwit)
2025-04-02 11:22:54 +10:30
Rusty Russell
5ff84aece9 lightningd: mangle parameter names in bitcoind_getrawblockbyheight_ so mocks don't get shadow warning.
When we make mocks (which the next patch will do), these names cause a warning:

```
wallet/test/run-db.c:32:64: error: declaration of ‘bitcoind’ shadows a parameter [-Werror=shadow=compatible-local]
   32 |                                    void (*cb)(struct bitcoind *bitcoind UNNEEDED,
wallet/test/run-db.c:30:53: note: shadowed declaration is here
   30 |                                    struct bitcoind *bitcoind UNNEEDED,
wallet/test/run-db.c:33:51: error: declaration of ‘height’ shadows a parameter [-Werror=shadow=compatible-local]
   33 |                                               u32 height UNNEEDED,
wallet/test/run-db.c:31:40: note: shadowed declaration is here
   31 |                                    u32 height UNNEEDED,
```

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2025-04-02 11:22:54 +10:30
Rusty Russell
52dfe9b52d wallet: extract "got utxo" function out of wallet_extract_owned_outputs.
We're going to want it for our rescan code.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2025-04-02 11:22:54 +10:30
Rusty Russell
8976cc33a8 wallet: remove unused total arg from wallet_extract_owned_outputs.
No caller uses it.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2025-04-02 11:22:54 +10:30
Rusty Russell
68f3649d6b wallet: do change db to watch both p2tr and p2wkph for not-yet-closed channels.
It's a bit more work to watch multiple addresses, but that's a small
price to pay for each channel.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2025-04-02 11:22:54 +10:30
Rusty Russell
d40da2b671 lightningd: make sure we register all addresses at opening if peer doesn't support OPT_SHUTDOWN_ANYSEGWIT.
We select the close key index at opening time, but the non-DF code didn't correctly register the
address as possibly used for P2WPKH for older nodes.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
Changelog-Fixed: wallet: we could miss our own returned outputs on mutual closes if peer doesn't support option_shutdown_anysegwit (you will still need to rescan after update, if this happened to you!)
Reported-by: Grubles
2025-04-02 11:22:54 +10:30
Rusty Russell
46690cb2a6 pytest: replicate error where we could miss our returned funds on mutual close.
1. Peer has to not support option_shutdown_anysegwit.
2. We have to restart between opening and closing the channel.
3. We won't see the to-us output, since it's p2wpkh not p2tr.

This bug was introduced in 24.11.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2025-04-02 11:22:54 +10:30
Rusty Russell
462e59823e pytest: generate broken db examples now, before we fix them.
We'll need these for our migration tests, so we need to generate "bad" dbs
now.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2025-04-02 11:22:54 +10:30
Rusty Russell
498c789c67 pyln-testing: routines to save/restore entire blockchain.
Good for making test snapshots.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2025-04-02 11:22:54 +10:30
Rusty Russell
6a81f0733a wallet: don't assume wally_tx outputs tal_bytelen(script) is the same as script_len.
It seems to be here, but it wouldn't have to be, so use the explicit length.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2025-04-02 11:22:54 +10:30
Rusty Russell
e82f0c42f3 lightningd: don't spam logs on dangling outgoing HTLCs.
We pre-close incoming under some circumstances, so this does happen (it
didn't when this code was written).  Don't walk all the HTLCs complaining
about them in this case, and don't freak out.

Changelog-Fixed: lightningd: incorrect spamming of log and potential crash on testnet case of duplicate HTLCs and slow closing.
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
Fixes: https://github.com/ElementsProject/lightning/issues/8176
2025-04-02 11:22:39 +10:30
Rusty Russell
19f76e1f1f lightningd: fix anchorspend HTLC deadline logic.
It's not the *outgoing* HTLC which sets the deadline, it's the incoming.

Reported-by: @whitslack
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
Changelog-Fixed: Protocol: Egregious anchor fee paid for unilateral close txs due to HTLC timeouts; it's not as urgent as our code made out!
2025-04-01 18:29:08 -05:00
Rusty Russell
1f0506352e lightningd: allow bitcoind_getrawblockbyheight callback to free call struct.
Use the indirect-free trick, otherwise this can happen:

```
2025-03-28T10:46:16.437Z BROKEN lightningd: FATAL SIGNAL 6 (version v25.02)
2025-03-28T10:46:16.437Z BROKEN lightningd: backtrace: common/daemon.c:41 (send_backtrace) 0x6447525af68c
2025-03-28T10:46:16.437Z BROKEN lightningd: backtrace: common/daemon.c:78 (crashdump) 0x6447525af6db
2025-03-28T10:46:16.437Z BROKEN lightningd: backtrace: ./signal/../sysdeps/unix/sysv/linux/x86_64/libc_sigaction.c:0 ((null)) 0x7783e2c4532f
2025-03-28T10:46:16.437Z BROKEN lightningd: backtrace: ./nptl/pthread_kill.c:44 (__pthread_kill_implementation) 0x7783e2c9eb2c
2025-03-28T10:46:16.437Z BROKEN lightningd: backtrace: ./nptl/pthread_kill.c:78 (__pthread_kill_internal) 0x7783e2c9eb2c
2025-03-28T10:46:16.437Z BROKEN lightningd: backtrace: ./nptl/pthread_kill.c:89 (__GI___pthread_kill) 0x7783e2c9eb2c
2025-03-28T10:46:16.437Z BROKEN lightningd: backtrace: ../sysdeps/posix/raise.c:26 (__GI_raise) 0x7783e2c4527d
2025-03-28T10:46:16.437Z BROKEN lightningd: backtrace: ./stdlib/abort.c:79 (__GI_abort) 0x7783e2c288fe
2025-03-28T10:46:16.437Z BROKEN lightningd: backtrace: ccan/ccan/tal/tal.c:95 (call_error) 0x644752675535
2025-03-28T10:46:16.437Z BROKEN lightningd: backtrace: ccan/ccan/tal/tal.c:169 (check_bounds) 0x6447526755de
2025-03-28T10:46:16.437Z BROKEN lightningd: backtrace: ccan/ccan/tal/tal.c:180 (to_tal_hdr) 0x644752675618
2025-03-28T10:46:16.437Z BROKEN lightningd: backtrace: ccan/ccan/tal/tal.c:525 (tal_free) 0x644752676001
2025-03-28T10:46:16.437Z BROKEN lightningd: backtrace: lightningd/bitcoind.c:509 (getrawblockbyheight_callback) 0x64475252c01b
2025-03-28T10:46:16.437Z BROKEN lightningd: backtrace: lightningd/plugin.c:661 (plugin_response_handle) 0x64475257be0a
```

Changelog-Fixed: lightningd: occasional crash on bitcoind callback.
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2025-04-01 13:29:28 -05:00
Rusty Russell
ee2ec8befa trace: minimal fix to avoid crash when > 128 traces active.
chanbackup with many peers can do more than 128 concurrent rpc commands.
autoclean is the other plugin which can do many requests at once, so I
expect a similar issue there.

I tested this by rebuilding with `MAX_ACTIVE_SPANS` 1, which autoclean
tests triggered immediately.

The real fix is probably to use a hash table with a large initial size.

```
Mar 24 06:30:45 mlbb2 sh[28000]: chanbackup: common/trace.c:190: trace_span_slot: Assertion `s' failed.
Mar 24 06:30:45 mlbb2 sh[28000]: chanbackup: FATAL SIGNAL 6 (version v25.02)
Mar 24 06:30:45 mlbb2 sh[28000]: 0x5575232bac4f send_backtrace
Mar 24 06:30:45 mlbb2 sh[28000]:         common/daemon.c:33
Mar 24 06:30:45 mlbb2 sh[28000]: 0x5575232baceb crashdump
Mar 24 06:30:45 mlbb2 sh[28000]:         common/daemon.c:78
Mar 24 06:30:45 mlbb2 sh[28000]: 0x7f2958cd851f ???
Mar 24 06:30:45 mlbb2 sh[28000]:         ./signal/../sysdeps/unix/sysv/linux/x86_64/libc_sigaction.c:0
Mar 24 06:30:45 mlbb2 sh[28000]: 0x7f2958d2c9fc __pthread_kill_implementation
Mar 24 06:30:45 mlbb2 sh[28000]:         ./nptl/pthread_kill.c:44
Mar 24 06:30:45 mlbb2 sh[28000]: 0x7f2958d2c9fc __pthread_kill_internal
Mar 24 06:30:45 mlbb2 sh[28000]:         ./nptl/pthread_kill.c:78
Mar 24 06:30:45 mlbb2 sh[28000]: 0x7f2958d2c9fc __GI___pthread_kill
Mar 24 06:30:45 mlbb2 sh[28000]:         ./nptl/pthread_kill.c:89
Mar 24 06:30:45 mlbb2 sh[28000]: 0x7f2958cd8475 __GI_raise
Mar 24 06:30:45 mlbb2 sh[28000]:         ../sysdeps/posix/raise.c:26
Mar 24 06:30:45 mlbb2 sh[28000]: 0x7f2958cbe7f2 __GI_abort
Mar 24 06:30:45 mlbb2 sh[28000]:         ./stdlib/abort.c:79
Mar 24 06:30:45 mlbb2 sh[28000]: 0x7f2958cbe71a __assert_fail_base
Mar 24 06:30:45 mlbb2 sh[28000]:         ./assert/assert.c:94
Mar 24 06:30:45 mlbb2 sh[28000]: 0x7f2958ccfe95 __GI___assert_fail
Mar 24 06:30:45 mlbb2 sh[28000]:         ./assert/assert.c:103
Mar 24 06:30:45 mlbb2 sh[28000]: 0x5575232ab7fa trace_span_slot
Mar 24 06:30:45 mlbb2 sh[28000]:         common/trace.c:190
Mar 24 06:30:45 mlbb2 sh[28000]: 0x5575232abc9f trace_span_start
Mar 24 06:30:45 mlbb2 sh[28000]:         common/trace.c:267
Mar 24 06:30:45 mlbb2 sh[28000]: 0x5575232a7c34 send_outreq
Mar 24 06:30:45 mlbb2 sh[28000]:         plugins/libplugin.c:1112
```

Changelog-Fixed: autoclean/chanbackup: fixed tracepoint crash on large number of requests.
Fixes: https://github.com/ElementsProject/lightning/issues/8177
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2025-04-01 09:20:07 -05:00
Rusty Russell
8dae8be5fb common: fix crash when we have a localmod with unrepresentable fee values.
We handed NULL as the logcb, resulting in a very uninformative crash:

```
2025-03-14T03:46:36.447Z INFO    lightningd: Server started with public key 03d67f36c4f81789e2fe425028bacc96b199813eae426c517f589a45f1136c1fe5, alias Jubilee (color #dc42f4) and lightningd v25.02
topology: FATAL SIGNAL 11 (version v25.02)
0x560037f64aad send_backtrace
        common/daemon.c:33
0x560037f64b49 crashdump
        common/daemon.c:78
0x7f6c41ff351f ???
        ./signal/../sysdeps/unix/sysv/linux/x86_64/libc_sigaction.c:0
0x0 ???
        ???:0
```

Changelog-Fixed: `topology` crash on invoice creation if a peer had a really high feerate.
Fixes: https://github.com/ElementsProject/lightning/issues/8156
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2025-04-01 16:33:23 +10:30
Christian Decker
f38cc0e897 chore: Add a simple pre-commit config
By limiting the commits that we look at to the changes since `master` we
can incrementally pull files under the coverage of these lints and checks.

Changelog-None: Not applicable, this is DX
2025-04-01 13:33:41 +10:30
ShahanaFarooqui
0dee58ca56 docs: Update instructions to append rcN to release candidates
Changelog-None.

Update doc/contribute-to-core-lightning/release-checklist.md

Co-Authored-By: Alex Myers <95372134+endothermicdev@users.noreply.github.com>
2025-04-01 13:30:22 +10:30
ShahanaFarooqui
b58a6708fc dev: Start dev-listaddrs index from 1 not 0
Changelog-None.
2025-04-01 12:55:54 +10:30
ShahanaFarooqui
63e15c1114 docs: Update Security Information on Doc Portal
Changelog-None
2025-03-28 11:51:54 +01:00
Rusty Russell
6a9fd02d93 pytest: fix flake in test_blindedpath_privchan.
We reconnect from l3->l2, but l2 is also trying to reconnect and
we can race:

```
        # Now try when l3 uses scid for entry point of blinded path.
        l3.stop()
        l3.daemon.opts['dev-invoice-bpath-scid'] = None
        l3.start()
>       l3.rpc.connect(l2.info['id'], 'localhost', l2.port)

tests/test_pay.py:5667:
...
>           raise RpcError(method, payload, resp['error'])
E           pyln.client.lightning.RpcError: RPC call failed: method: connect, payload: {'id': '022d223620a359a47ff7f7ac447c85c46c923da53389221a0054c11c1e3ca31d59', 'host': 'localhost', 'port': 33557}, error: {'code': 402, 'message': 'disconnected during connection'}
```

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2025-03-24 13:59:58 +10:30
Rusty Russell
edb386558c lightningd: avoid high memory usage spike at startup.
I saw this while watching top, and tracked it down.  We load all the
plugins to checksum them at startup:

```
$ ms_print massif.out.3312805 | head -n 50
--------------------------------------------------------------------------------
Command:            lightningd/lightningd.real --developer --log-level=trace --cltv-delta=6 --cltv-final=5 --watchtime-blocks=5 --rescan=1 --disable-dns --lightning-dir=/tmp/ltests-roazlc8h/test_xpay_fake_channeld_1/lightning-1/ --addr=127.0.0.1:46337 --allow-deprecated-apis=false --network=regtest --ignore-fee-limits=false --bitcoin-rpcuser=rpcuser --bitcoin-rpcpassword=rpcpass --bitcoin-datadir=/tmp/ltests-roazlc8h/test_xpay_fake_channeld_1/lightning-1/ --dev-fast-gossip --dev-bitcoind-poll=1 --log-file=- --log-file=/tmp/ltests-roazlc8h/test_xpay_fake_channeld_1/lightning-1/log --log-prefix=lightningd-1  --dev-fail-on-subdaemon-fail --dev-no-reconnect --autoconnect-seeker-peers=0 --subdaemon=channeld:../tests/plugins/channeld_fakenet --dev-throttle-gossip --grpc-port=37819 --dev-crash-after=3600 --bitcoin-rpcport=51623
Massif arguments:   (none)
ms_print arguments: massif.out.3312805
--------------------------------------------------------------------------------

    MB
446.5^#
     |#
     |#
     |#
     |#
     |#
     |#
     |#
     |#
     |#
     |#
     |#
     |#
     |#
     |#
     |#
     |#
     |#
     |#
     |#    :: : ::@@:@:::::::::::::::::::::::::::@@::::::::::::::@::::@:::::::
   0 +----------------------------------------------------------------------->Gi
     0                                                                   75.66

Number of snapshots: 57
 Detailed snapshots: [1 (peak), 2, 10, 12, 33, 45, 49]

--------------------------------------------------------------------------------
  n        time(i)         total(B)   useful-heap(B) extra-heap(B)    stacks(B)
--------------------------------------------------------------------------------
  0              0                0                0             0            0
  1    295,677,530      468,189,872      447,087,069    21,102,803            0
95.49% (447,087,069B) (heap allocation functions) malloc/new/new[], --alloc-fns, etc.
->95.35% (446,440,727B) 0x2EFB99: tal_resize_ (tal.c:755)
| ->94.23% (441,180,860B) 0x2EBCD1: grab_fd (grab_file.c:45)
| | ->94.23% (441,180,860B) 0x2EBD54: grab_file (grab_file.c:63)
| |   ->94.23% (441,180,860B) 0x1A5CF7: file_checksum (plugin.c:315)
| |     ->94.23% (441,180,860B) 0x1A5EF1: plugin_register (plugin.c:355)
| |       ->94.23% (441,180,860B) 0x1AC62E: plugins_set_builtin_plugins_dir (plugin.c:2532)
| |         ->94.23% (441,180,860B) 0x16D614: find_subdaemons_and_plugins (lightningd.c:569)
| |           ->94.23% (441,180,860B) 0x16E9A1: main (lightningd.c:1226)
| |
| ->01.11% (5,219,417B) 0x2EBC32: grab_fd (grab_file.c:38)
```

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2025-03-24 13:59:58 +10:30
Rusty Russell
922d78e89b pytest: fix flake in test_onionmessage_ratelimit.
By submitting them all at once, rather than serially, we should *definitely* hit the
ratelimit.  We can also reduce the timeout (from 60 seconds) to speed the test up.

```
    @pytest.mark.slow_test
    def test_onionmessage_ratelimit(node_factory):
        l1, l2 = node_factory.line_graph(2, fundchannel=False,
                                         opts={'allow_warning': True})

        offer = l2.rpc.call('offer', {'amount': '2msat',
                                      'description': 'simple test'})

        # Hopefully we can do this fast enough to reach ratelimit!
>       with pytest.raises(RpcError, match="Timeout waiting for response"):
E       Failed: DID NOT RAISE <class 'pyln.client.lightning.RpcError'>

tests/test_pay.py:5825: Failed
```

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2025-03-24 13:59:58 +10:30
Rusty Russell
2050f9afd9 pytest: fix flake in test_setconfig_access.
We play with directory permissions, but sqlites needs that, and sometimes (due to a timer, perhaps?)
it gets really upset about it:

```
lightningd-1 2025-03-16T23:29:58.506Z INFO    lightningd: Server started with public key 0266e4598d1d3c415f572a8488830b60f7e744ed9235eb0b1ba93283b315c03518, alias JUNIORBEAM-f91eb11-modded (color #0266e4) and lightningd f91eb11-modded
lightningd-1 2025-03-16T23:29:58.617Z DEBUG   lightningd: Adding block 101: 55af171ade598f8c4f9a494eaaffe6b9f5ea64c7b0f3b273694148adf7ad7385
lightningd-1 2025-03-16T23:29:58.752Z TRACE   lightningd: Calling rpc_command hook of plugin cln-xpay
lightningd-1 2025-03-16T23:29:58.764Z TRACE   lightningd: Plugin cln-xpay returned from rpc_command hook call
lightningd-1 2025-03-16T23:29:58.784Z TRACE   lightningd: Calling rpc_command hook of plugin cln-xpay
lightningd-1 2025-03-16T23:29:58.840Z TRACE   lightningd: Plugin cln-xpay returned from rpc_command hook call
lightningd-1 2025-03-16T23:29:58.854Z TRACE   lightningd: Calling rpc_command hook of plugin cln-xpay
lightningd-1 2025-03-16T23:29:58.865Z DEBUG   gossipd: REPLY WIRE_GOSSIPD_NEW_BLOCKHEIGHT_REPLY with 0 fds
lightningd-1 2025-03-16T23:29:58.901Z **BROKEN** lightningd: Error executing statement: db/exec.c:108: UPDATE vars SET intval = intval + 1 WHERE name = 'data_version' AND intval = ?: attempt to write a readonly database
lightningd-1 2025-03-16T23:29:58.916Z **BROKEN** lightningd: Error executing statement: db/exec.c:108: UPDATE vars SET intval = intval + 1 WHERE name = 'data_version' AND intval = ?: attempt to write a readonly database
lightningd-1 2025-03-16T23:29:58.941Z **BROKEN** lightningd: FATAL SIGNAL 6 (version f91eb11-modded)
{'github_repository': 'ElementsProject/lightning', 'github_sha': 'f91eb118388dc1455c67d16079168fd0267ba248', 'github_ref': 'refs/pull/8112/merge', 'github_ref_name': 'HEAD', 'github_run_id': 13888173501, 'github_head_ref': 'flake-memleak', 'github_run_number': 12573, 'github_base_ref': 'master', 'github_run_attempt': '1', 'testname': 'test_setconfig_access', 'start_time': 1742167762, 'end_time': 1742167800, 'outcome': 'fail'}
----------------------------- Captured stderr call -----------------------------
Error executing statement: db/exec.c:108: UPDATE vars SET intval = intval + 1 WHERE name = 'data_version' AND intval = ?: attempt to write a readonly database
lightningd: FATAL SIGNAL 6 (version f91eb11-modded)
Log dumped in /tmp/lightning-crash.log.20250316232958
Lost connection to the RPC socket.Lost connection to the RPC socket.
=========================== short test summary info ============================
FAILED tests/test_misc.py::test_setconfig_access - AssertionError: Regex pattern did not match.
 Regex: 'Cannot write to config file /tmp/ltests-22a5dz1j/test_setconfig_access_1/lightning-1/regtest/config'
 Input: "RPC call failed: method: check, payload: {'command_to_check': 'setconfig', 'config': 'min-capacity-sat', 'val': 1000000}, error: Connection to RPC server lost."
ERROR tests/test_misc.py::test_setconfig_access - ValueError:
Node errors:
 - lightningd-1: had BROKEN messages
 - lightningd-1: Node exited with return code -6
```

So we move the db file for sqlite.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2025-03-24 13:59:58 +10:30
Rusty Russell
248677d78c pytest: fix flake in test_last_stable_connection.
```
>       assert only_one(l1.rpc.listpeerchannels()['channels'])['last_stable_connection'] > recon_time + STABLE_TIME
E       assert 1742167762 > (1742167702.0235627 + 60)

tests/test_connection.py:4545: AssertionError
```

Indeed, the > should be >=.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2025-03-24 13:59:58 +10:30
Rusty Russell
8cbb2457d9 pytest: fix flake in splice gossip test.
We can in fact see the new channel before this line is called:

```
2025-03-15T12:31:04.1472196Z     @pytest.mark.openchannel('v1')
2025-03-15T12:31:04.1472616Z     @pytest.mark.openchannel('v2')
2025-03-15T12:31:04.1473317Z     @unittest.skipIf(TEST_NETWORK != 'regtest', 'elementsd doesnt yet support PSBT features we need')
2025-03-15T12:31:04.1474271Z     def test_splice_gossip(node_factory, bitcoind):
2025-03-15T12:31:04.1475078Z         l1, l2, l3 = node_factory.line_graph(3, fundamount=1000000, wait_for_announce=True, opts={'experimental-splicing': None})
2025-03-15T12:31:04.1475781Z
2025-03-15T12:31:04.1476052Z         chan_id = l1.get_channel_id(l2)
2025-03-15T12:31:04.1476460Z         pre_splice_scid = first_scid(l1, l2)
2025-03-15T12:31:04.1476844Z
2025-03-15T12:31:04.1477134Z         # add extra sats to pay fee
2025-03-15T12:31:04.1477741Z         funds_result = l1.rpc.fundpsbt("109000sat", "slow", 166, excess_as_change=True)
2025-03-15T12:31:04.1478345Z
2025-03-15T12:31:04.1478765Z         result = l1.rpc.splice_init(chan_id, 100000, funds_result['psbt'])
2025-03-15T12:31:04.1479432Z         result = l1.rpc.splice_update(chan_id, result['psbt'])
2025-03-15T12:31:04.1479994Z         assert(result['commitments_secured'] is False)
2025-03-15T12:31:04.1480584Z         result = l1.rpc.splice_update(chan_id, result['psbt'])
2025-03-15T12:31:04.1481089Z         assert(result['commitments_secured'] is True)
2025-03-15T12:31:04.1481386Z         result = l1.rpc.signpsbt(result['psbt'])
2025-03-15T12:31:04.1481860Z         result = l1.rpc.splice_signed(chan_id, result['signed_psbt'])
2025-03-15T12:31:04.1482403Z
2025-03-15T12:31:04.1485960Z         wait_for(lambda: only_one(l2.rpc.listpeerchannels(l1.info['id'])['channels'])['state'] == 'CHANNELD_AWAITING_SPLICE')
2025-03-15T12:31:04.1489978Z         wait_for(lambda: only_one(l1.rpc.listpeerchannels(l2.info['id'])['channels'])['state'] == 'CHANNELD_AWAITING_SPLICE')
2025-03-15T12:31:04.1490796Z
2025-03-15T12:31:04.1491223Z         bitcoind.generate_block(6, wait_for_mempool=result['txid'])
2025-03-15T12:31:04.1491767Z
2025-03-15T12:31:04.1492213Z         # l3 will see channel dying, but still consider it OK for 12 blocks.
2025-03-15T12:31:04.1493174Z         l3.daemon.wait_for_log(f'gossipd: channel {pre_splice_scid} closing soon due to the funding outpoint being spent')
2025-03-15T12:31:04.1494422Z         assert len(l3.rpc.listchannels(short_channel_id=pre_splice_scid)['channels']) == 2
2025-03-15T12:31:04.1495293Z >       assert len(l3.rpc.listchannels(source=l1.info['id'])['channels']) == 1
2025-03-15T12:31:04.1495937Z E       AssertionError: assert 2 == 1
2025-03-15T12:31:04.1503185Z E        +  where 2 = len([{'active': True, 'amount_msat': 1000000000, 'base_fee_millisatoshi': 1, 'channel_flags': 1, ...}, {'active': True, 'amount_msat': 1100000000, 'base_fee_millisatoshi': 1, 'channel_flags': 1, ...}])
```

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2025-03-24 13:59:58 +10:30
Rusty Russell
5ba5546192 pytest: fix flake in test_fetchinvoice
The sleep was simply allowing gossip to propagate, so (sometimes) l4 can connect to l3/l1.
We really want to suppress the blinded path on l2:

```
2025-03-03T05:25:16.6928072Z >       l4.rpc.call('fetchinvoice', {'offer': offer3['bolt12']})
2025-03-03T05:25:16.6928280Z
2025-03-03T05:25:16.6928367Z tests/test_pay.py:4540:
2025-03-03T05:25:16.6928609Z _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-03-03T05:25:16.6928929Z contrib/pyln-testing/pyln/testing/utils.py:760: in call
...
2025-03-03T05:25:16.6956050Z E           pyln.client.lightning.RpcError: RPC call failed: method: fetchinvoice, payload: {'offer': 'lno1qgsqvgnwgcg35z6ee2h3yczraddm72xrfua9uve2rlrm9deu7xyfzrcgqyqs5pn0venx2u3nzrhqxhftzxfdlwsnfcgw2sy8t5mxa0ytcdfat2nkdwqvpy9nnsa9mzzaqfwys22njn0v5g3jswhdh684hnlnkvd5pme28q5hgyyhshhmntd6qqsz40a4renm8a94r9xf5eez73ygcmendmd9utwmx0kzlp0lwd9sq98sqvutrneuljglxekynj2wdhpsa36ra3ae7uql9g79w9qqc0rqrunkystxgsz2reyay8hdtzwjew38w2u4xavpq2fm360hd75pkyuhpar0adgu93z8gn0jsyxganyhelch7savw6vrgqpj80cdc5qkwkaz0dk65cwyatgmhszpv72axqz6ldvcjq9crzevzpd3aeet607hq7sk0fvz0musdn7r96w6zcssytfzxcs2xkdy0lml0tzy0jzugmyj8kjn8zfzrgq9fsgurc72x82e'}, error: {'code': 1003, 'message': 'Failed: could not route or connect directly to blinded path at 035d2b1192dfba134e10e540875d366ebc8bc353d5aa766b80c090b39c3a5d885d: {"code":400,"message":"Unable to connect, no address known for peer"}'}
```

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2025-03-24 13:59:58 +10:30
Rusty Russell
04b21c34d3 lightningd: fix overzealous memleak report.
Found by CI, not a real leak.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2025-03-24 13:59:58 +10:30
ShahanaFarooqui
08210dab47 docs: Update Security Information
Changelog-None.
2025-03-22 14:04:24 +10:30
ShahanaFarooqui
b261e82e6f docs: Remove lightning-dev mailing list from README
Changelog-None.
2025-03-22 14:03:36 +10:30
Jon Griffiths
8fc4cb6bef hsmd: enable caching of sub-hashes when signing our PSBT inputs
Enabling the cache makes signing significantly faster for segwit inputs,
particularly taproot which was designed with caching in mind.

Changelog-None

Signed-off-by: Jon Griffiths <jon_p_griffiths@yahoo.com>
2025-03-21 09:48:57 +10:30
Jon Griffiths
0d854ba3d8 psbt: avoid duplicating the input string when parsing from base64
Changelog-None

Signed-off-by: Jon Griffiths <jon_p_griffiths@yahoo.com>
2025-03-21 09:48:57 +10:30
Jon Griffiths
960a44115b wally: update libwally to 1.4.0
Changelog-Changed: Update libwally to 1.4.0

Signed-off-by: Jon Griffiths <jon_p_griffiths@yahoo.com>
2025-03-21 09:48:57 +10:30
Christian Decker
2b761b00b8 pytest: Test that we don't forget zeroconf channels
Modified by Rusty:
- Simplify (we only need to suppress l1's txs, since it opens)
- Use synchronize_blockheight instead of log messages to ensure l2 has processed the block
- Use listpeerchannels instead of log messages for balance (should be more robust against changes)
- Open-code assertions for better debugging if they're wrong.
2025-03-19 17:32:26 +01:00
Christian Decker
66deb4dee5 opening: Do not forget a zeroconf channel we own funds in
Changelog-Fixed opening: We no longer forget zeroconf channels in which we own funds due to a confirmation timeout
2025-03-19 17:32:26 +01:00
Rusty Russell
71eb04064c common: implement op_return test.
Since we included the spec for it, this is a good time to implement
it.

I also asked chatgpt to write some unit tests.  I had to mangle them a
bit, but it probably saved me a few minutes.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2025-03-18 14:30:58 +10:30
Rusty Russell
733efcf7dd BOLTs: import spec additions for option_simple_close.
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2025-03-18 14:30:58 +10:30
Rusty Russell
58e14284e2 BOLTs: Add typo fixes and clarifications from "More clarifications around channel_announcement handling (#1220)"
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2025-03-18 14:30:58 +10:30
Rusty Russell
67c91a7e5c BOLTs: Update to version with peer storage merged.
Unfortunately a spec typo means the data fields are missing (PR pending),
so we still patch those in.

The message "your_peer_storage" got renamed to "peer_storage_retrieval",
and the option "want_peer_backup_storage" was removed.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
Changelog-EXPERIMENTAL: `experimental-peer-storage` now only advertizes feature 43, not 41.
2025-03-18 14:30:58 +10:30
Rusty Russell
e832784cba BOLTS: update which fixes BIP353 quotes, missing invreq field in invoices.
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2025-03-18 14:30:58 +10:30
Rusty Russell
2e81a40d77 BOLTs: update for BOLT, which removes requirement to wait 6 blocks before sending announcement_signatures.
We have a replacement quote which is suitable here, but it comes in a later BOLT commit.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2025-03-18 14:30:58 +10:30
Rusty Russell
0e7615b1b7 plugins/topology: remove local channels from listchannels.
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
Changelog-Removed: RPC `listchannels` no longer includes private local channels (deprecated v23.08, disabled by default in v24.11).
2025-03-12 09:26:08 +10:30
Rusty Russell
73fc9b0c2a plugins: all plugins must now support non-numeric JSON RPC id fields.
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
Changelog-Removed: plugins which didn't accept string JSON RPC fields (deprecated v23.08, disabled by default in v24.11).
2025-03-12 09:26:08 +10:30
Rusty Russell
d69499b558 lightningd: no longer allow plugin flag options with non-false default values.
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
Changelog-Removed: default settings for flag options in plugins which aren't "false".
2025-03-12 09:26:08 +10:30
Rusty Russell
f95b542c1e plugins: no longer accept 0/1 for boolean options.
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
Changelog-Removed: allowing 0/1 instead of false/true for plugin options (deprecated v23.08, disabled by default in v24.11).
2025-03-12 09:26:08 +10:30
Rusty Russell
c1c93a3212 lightningd: remove announce-addr-dns flag.
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
Changelog-Removed: Config: `announce-addr-dns` (deprecated v23.08, disabled in v24.11).
2025-03-12 09:26:08 +10:30
Rusty Russell
7fbc814796 lightningd: remove --bind-addr and --addr munging on onions and local sockets.
Changelog-Removed: --bind-addr and --addr on onion addresses and local sockets (deprecated v23.08, disabled by default in v24.11).
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2025-03-12 09:26:08 +10:30
Rusty Russell
f2852846d2 lightningd: remove accept-htlc-tlv-types.
Changelog-Removed: accept-htlc-tlv-types (deprecated v23.08, disabled by default in v24.11).
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2025-03-12 09:26:08 +10:30
Rusty Russell
4f17672001 lightningd: disable old notification fields.
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
Changelog-Removed: connection/disconnection/block_added notification raw fields (deprecated v23.08, disabled by default in v24.11).
2025-03-12 09:26:08 +10:30
Rusty Russell
cce0212819 lightningd: remove old listconfigs output.
We haven't printed this since v24.08.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
Changelog-Removed: listconfigs raw listing (deprecated v23.08, disabled by default in v24.11).
2025-03-12 09:26:08 +10:30
Rusty Russell
371965cec3 Makefile: update CLN_NEXT_VERSION.
We now have to explicitly enable various deprecated commando commands, and now
when deprecations are disabled, we honour missing MPP option in bolt12 invoices.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2025-03-12 09:26:08 +10:30
Rusty Russell
c05ffb2fb1 doc: remove documentation for disabled commando commands.
When we update the CLN_NEXT_VERSION, these will only be available with --i-promise-to-fix-broken-api-user.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2025-03-12 09:26:08 +10:30
Rusty Russell
421adc6957 libplugin: take into account --i-promise-to-fix-broken-api-user for output.
Somehow we missed this when we added libplugin support.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2025-03-12 09:26:08 +10:30
Rusty Russell
ba8b5a6636 pytest: don't need allow-deprecated-apis in test_commando/test_commando_stress any more.
In d18f564324 "pytest: stop using
deprecated commando_rune commands." we stopped using deprecated commands in these tests,
but we didn't remove the 'allow-deprecated-apis' flag.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2025-03-12 09:26:08 +10:30
Rusty Russell
97d823ba1d lightningd: fix use of deprecation macro.
_in_ versions complain if used, _out_ don't (since we don't know if they are
going to use it).  This was the wrong choice, and thus causes a BROKEN log
message when we update CLN_NEXT_VERSION.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2025-03-12 09:26:08 +10:30
daywalker90
5390882143 crates: bump versions to 0.4.0
Changelog-None
2025-03-11 11:10:11 -05:00
ShahanaFarooqui
b5eef8af4d dockerfile: Add poetry lock before export for wss-proxy
The current docker build failed with Error `1.082 pyproject.toml changed significantly since poetry.lock was last generated. Run `poetry lock` to fix the lock file.`. Adding `poetry lock` command before `poetry export` will regenerate the lock file.

Changelog-None.
2025-03-05 18:25:24 -06:00
ShahanaFarooqui
d40191eeb6 ci: Fixed python to version 3.10
The pypi publishing failed due to `ERROR: No matching distribution found for poetry==2.1.1`. Fixing Python version resolves the issue.
2025-03-05 18:25:24 -06:00
ShahanaFarooqui
162fcb754d tools: Create config.vars before ./configure 2025-03-05 18:25:24 -06:00
Alex Myers
427c4c5ce0 meta: update changelog for 25.02
Changelog-None
2025-03-04 20:58:46 -06:00
Rusty Russell
ac596c8e08 offers: don't add blinded path from a disconnected peer.
Really, any peer without a live channel is a bad prospect.

This requires us to wire the "enabled" flag through listincoming:
fortunately that's an internal, undocumented interface, so we don't
have a schema change.

Changelog-Fixed: Offline peers no longer selected for blinded paths..

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
Fixes: https://github.com/ElementsProject/lightning/issues/8127
2025-03-04 20:13:49 -06:00
Rusty Russell
d47b188cab pytest: add a test that we don't use an offline peer for offer paths.
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2025-03-04 20:13:49 -06:00
Rusty Russell
c92c384875 onchaind: fix crash if we enounter a tx with no witness.
This can happen if a descendent tx has no witness and we don't tell the main daemon
in time that we're not iterested.

Fixes: https://github.com/ElementsProject/lightning/issues/8133
Changelog-Fixed: lightningd: onchaind crash when seeing unrelated txs (usually when catching up with old closes)
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2025-03-04 17:58:29 -06:00
Alex Myers
1e5a577fb2 gossipd: fix typo
Changelog-None
2025-03-03 12:25:26 -06:00
Rusty Russell
1605c13c1a lightningd: fix crash in onchaind replay.
If a tx has already spent one tx we're watching, and it spends another,
we try to add it to the hash table twice, which isn't allowed:

```
2025-02-28T23:00:32.155Z **BROKEN** lightningd: backtrace: ../sysdeps/unix/sysv/linux/raise.c:51 (__GI_raise) 0x7fab2e363d51
2025-02-28T23:00:32.155Z **BROKEN** lightningd: backtrace: ./stdlib/abort.c:79 (__GI_abort) 0x7fab2e34d536
2025-02-28T23:00:32.155Z **BROKEN** lightningd: backtrace: ./assert/assert.c:92 (__assert_fail_base) 0x7fab2e34d40e
2025-02-28T23:00:32.155Z **BROKEN** lightningd: backtrace: ./assert/assert.c:101 (__GI___assert_fail) 0x7fab2e35c6d1
2025-02-28T23:00:32.155Z **BROKEN** lightningd: backtrace: lightningd/onchain_control.c:48 (replay_tx_hash_add) 0x556928d4e114
2025-02-28T23:00:32.155Z **BROKEN** lightningd: backtrace: lightningd/onchain_control.c:365 (replay_watch_tx) 0x556928d4e114
2025-02-28T23:00:32.155Z **BROKEN** lightningd: backtrace: lightningd/onchain_control.c:419 (replay_block) 0x556928d4e835
2025-02-28T23:00:32.155Z **BROKEN** lightningd: backtrace: lightningd/bitcoind.c:506 (getrawblockbyheight_callback) 0x556928d1c791
```

Fixes: #8131
Reported-by: Vincenzo Palazzo
Changelog-None: introduced this release, when we banned htable dups.
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2025-03-02 16:06:34 -06:00
Alex Myers
3f81dc0221 meta: update CHANGELOG for 25.02rc3
Changelog-None
2025-02-27 15:14:41 -06:00
Alex Myers
8f891ce491 doc: update examples without blinded path hop 2025-02-27 13:53:10 -06:00
Rusty Russell
d2f4196179 offers: don't send blinded path to neighbor for *invoices*.
In 6e4ff6a7d2 ("offers: add a blinded path
if we have no advertized address") we were overzealous, and set blinded
paths not just for offers and invoicerequests, but for invoices themselves.

This has revealed various interop issues (which is great, but not good
for our users!) so we should disable that.  It also reduces the reliability
of payments in general.

Changelog-None: fixes previously overzealous addition
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2025-02-27 13:53:10 -06:00
daywalker90
05f0100e7d msggen: comply with grpc and rust naming conventions
Changelog-Changed: Some enums, structs, functions in pyln-grpc-proto/cln-grpc/cln-rpc
have been slightly renamed so they follow grpc and rust's naming convention
2025-02-27 11:53:48 -06:00
daywalker90
3e461036b3 msggen: add InjectOnionMessage
Changelog-None
2025-02-27 11:53:48 -06:00
daywalker90
5dab24ff38 msggen: add channel_state_changed notification
Changelog-None
2025-02-27 11:53:48 -06:00
Alex Myers
6368aa953f meta: update changelog for v25.02rc2
Changelog-None
2025-02-26 15:49:21 -06:00
Rusty Russell
2408233b2e pay: use correct CLTV values for blinded paths.
We added twice, which caused spurious failures in real-world cases.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
Reported-by: https://github.com/hMsats
Fixes: https://github.com/ElementsProject/lightning/issues/8119
Changelog-Fixed: `xpay` would double the CLTV values in blinded paths, sometimes causing spurious failures.
2025-02-26 14:26:47 -06:00
Rusty Russell
69476dbcab xpay: a test of a similar scenario to a real failure.
Use larger CLTVs and we see the failure from l3, complaining the CLTV is outside
the amount in the payment_constraint field, like:

```
Failing HTLC because of an invalid payload (TLV 10 pos 104): cltv_expiry 609 > payment_constraint 376
```

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2025-02-26 14:26:47 -06:00
Rusty Russell
10f333b041 devtools/bolt12-cli: fix interpretation of blindedpay, amounts.
The old blindedpay fields would have an entry per hop, but that was changed
to a single per-path entry.  The devtools hadn't caught up.

Similarly, it didn't like descriptionless offer fields in invreqs and invoices.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2025-02-26 14:26:47 -06:00
Rusty Russell
5e4c1b7839 lightningd: redo closing negotiation even if we consider channel closed.
This corner case started triggering on my machine with latest Bitcoind.

This test sabotages the closing negotiation, and as a result l1
doesn't see l2's CLOSING_SIGNED.  l2 is happy, however, and it is in
CLOSINGD_COMPLETE.  When l1 reconnects, it gets an error, and this causes
it to drop the unilateral tx to chain.

This unilateral tx from l1 replaces or races the mutual close tx from
l2, causing a unilateral close, which breaks our test.

Though this is a corner case, it's much friendlier to allow the
closing negotiation again until we actually see the close onchain.
This fixes the tests here, too.

```
    def test_closing_negotiation_reconnect(node_factory, bitcoind):
        disconnects = ['-WIRE_CLOSING_SIGNED',
                       '+WIRE_CLOSING_SIGNED']
        l1, l2 = node_factory.line_graph(2, opts=[{'disconnect': disconnects,
                                                   'may_reconnect': True},
                                                  {'may_reconnect': True}])
        l1.pay(l2, 200000000)
    
        assert bitcoind.rpc.getmempoolinfo()['size'] == 0
    
        l1.rpc.close(l2.info['id'])
        l1.daemon.wait_for_log(r'State changed from CHANNELD_NORMAL to CHANNELD_SHUTTING_DOWN')
        l2.daemon.wait_for_log(r'State changed from CHANNELD_NORMAL to CHANNELD_SHUTTING_DOWN')
    
        # Now verify that the closing tx is in the mempool.
        bitcoind.generate_block(6, wait_for_mempool=1)
        sync_blockheight(bitcoind, [l1, l2])
        for n in [l1, l2]:
            # Ensure we actually got a mutual close.
>           n.daemon.wait_for_log(r'Resolved FUNDING_TRANSACTION/FUNDING_OUTPUT by MUTUAL_CLOSE')

tests/test_closing.py:275: 
```

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
Changelog-Fixed: Protocol: We now renegotiate an interrupted close, even if we don't need it, instead of sending an error.
2025-02-26 10:22:03 -06:00
Rusty Russell
a4aa77761c lightningd: create helper routine to make socketpair for a channel.
This is a bit too much boilerplate for these, which mainly do the same
thing.

We add annotaitons to new_peer_fd so the compiler knows that it cannot
return NULL, otherwise with -O3 we get:

```
lightningd/peer_control.c: In function ‘peer_connected_hook_final’:
lightningd/peer_control.c:1388:28: error: ‘error’ may be used uninitialized in this function [-Werror=maybe-uninitialized]
 1388 |                       take(towire_connectd_peer_send_msg(NULL, &channel->peer->id,
      |                            ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~
lightningd/peer_control.c:1313:19: note: ‘error’ was declared here
 1313 |         const u8 *error;
      |                   ^~~~~
lightningd/peer_control.c: In function ‘peer_spoke’:
lightningd/peer_control.c:1999:28: error: ‘error’ may be used uninitialized in this function [-Werror=maybe-uninitialized]
 1999 |                       take(towire_connectd_peer_send_msg(NULL, &peer->id,
      |                            ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~
cc1: all warnings being treated as errors
make: *** [Makefile:311: lightningd/peer_control.o] Error 1
```

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2025-02-26 10:22:03 -06:00
Alex Myers
4f7df828b4 gossipd, chanbackup: reduce logging levels
The vast majority of incoming channel updates seem to be cut due
to age, which results in noisy logs.  Similarly, the chanbackup
logging verbosity might better match the equivalent actions in
channeld, which are at the debug level.

Fixes: #8058

Changelog-None: introduced in 25.02
2025-02-26 14:15:13 +10:30
Rusty Russell
79b28eb8c2 onchaind: tell lightningd correct nSequence value for local leases.
If the nSequence in the tx it produces is not at least the value we
test in the script, the tx will always fail:

```
error code: -26\nerror message:\nmandatory-script-verify-flag-failed (Locktime requirement not satisfied)
```

If we have a lease, the nSequence is max(lease-time-remaining,
to-self-delay), so have onchaind tell lightningd the correct nSequence.

Fixes: https://github.com/ElementsProject/lightning/issues/7460
Reported-by: https://github.com/pabpas
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
Changelog-EXPERIMENTAL: Correctly collect our own (delayed) funds if we have a unilateral close when we are still offering a lease.
2025-02-25 10:10:14 +10:30
Rusty Russell
5078e792e8 onchaind: don't tell lightningd to send OUR_DELAYED_RETURN_TO_WALLET too early (leases).
current height + to_self_delay[LOCAL] is correct normally, but if we
have an outstanding lease it's longer.  Not a big issue, because
lightningd will retry until its spendable, but wrong.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2025-02-25 10:10:14 +10:30
Rusty Russell
8c0b2334c1 pytest: add test that to-local output spend actually works during lease time.
What we expect to happen:

1. l3, which unilaterally closed, waits 4032 blocks (minus those mined) before
   trying to send get its "to_local" funds back.
2. This should then succeed.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2025-02-25 10:10:14 +10:30
Alex Myers
e96af42947 meta: update changelog for 25.02
Changelog-None
2025-02-24 16:06:41 -06:00
Alex Myers
091afee0ee wss-proxy: update dependencies
This should allow the last published version or the
local build (pyln-client v25.02)
2025-02-24 16:06:41 -06:00
Rusty Russell
4fdbd8ba98 lightningd: catch edits of config files *before* we're committed.
Another report, that we crash if it's edited.  We should check that too!

Reported-by: daywalker90
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2025-02-24 19:38:37 +10:30
Rusty Russell
5e79cd4608 lightningd: check for writability before allowing setconfig.
If we actually can't write it, we crash (to avoid an inconsistent
state), so sanity check FIRST.

Fixes: https://github.com/ElementsProject/lightning/issues/7964
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2025-02-24 19:38:37 +10:30
Rusty Russell
8127fcf825 pytest: don't add bookeeper-db option if bookkeeper is disabled.
There are other ways we can disable it, of course (e.g full path name)
but this is the most obvious.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2025-02-24 19:38:37 +10:30
Rusty Russell
989cf17982 setconfig: put vars in separate "config.setconfig" file.
This is neater than appending to some random file: we only do that once
if there's no "include" line to include a ".setconfig" file.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2025-02-24 19:38:37 +10:30
Rusty Russell
f4872f96db common: return location of a ".setconfig" file when we load config.
This is where we will put all the dynamic settings.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2025-02-24 19:38:37 +10:30
Rusty Russell
da2fb198c4 setconfig: make source for setconfig "setconfig transient".
Previously it would be the value of the previous config setting.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2025-02-24 19:38:37 +10:30
Rusty Russell
5a80223f3e setconfig: add transient option.
Changelog-Added: JSON-RPC: `setconfig` now has a `transient` flag which means it won't rewrite your config file.
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2025-02-24 19:38:37 +10:30
Rusty Russell
98f15aecf4 lightningd: remove redundant command_check_only()
setconfig_success does this itself at the start, so we don't need it here.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2025-02-24 19:38:37 +10:30
Aditya Sharma
2dcbc701e4 tests: Added test_emergencyrecoverpenaltytxn
This test would make sure that the node would publish a penalty txn when channel partner
cheats.
2025-02-22 11:51:54 -06:00
Aditya Sharma
b44ed32408 test_misc.py: Add test_emergencyrecover_old_format_handling
Key Changes:
 - Added encrypted_data which contains emergency.recover in the legacy format
 - Added assert to make sure we watch the funding txn
2025-02-22 11:51:54 -06:00
Aditya Sharma
1a54888e2d Update SCB on every commitment update and handle new format
The chanbackup plugin should update emergency.recover every time we
receive a new commitment secret.

Additionally, chanbackup should be able to serialize both the new
SCB format and the legacy format.

Key Changes:
 - Added a commitment_revocation plugin hook to update emergency.recover whenever a new revocation secret is received.
 - Implemented support for the new emergency.recover format while maintaining compatibility with the legacy format.
2025-02-22 11:51:54 -06:00
Aditya Sharma
ab3ad617ce peer_control: Update shainchain and basepoints
Add the latest shachain when we update the emergency.recover using staticbackup RPC.
2025-02-22 11:51:54 -06:00
Aditya Sharma
41c6e3306f wallet: Add 'wallet_stub_shachain_init' to persist shachain
This function enables direct persistence of shachain data, ensuring all relevant information is saved upon retrieval.

Key Changes:
 - Adds 'wallet_stub_shachain_init' function to store a retrieved shachain in the database.
 - Saves initial metadata ('min_index' and 'num_valid') to the 'shachains' table.
 - Iterates through known shachain secrets, adding each entry to 'shachain_known' with position, index, and hash.
2025-02-22 11:51:54 -06:00
Aditya Sharma
cf2bd9f616 lightningd: Modify stub_chan() to accomodate new fields
These fields enhance 'stub_chan' to make channels which are capable to
create penalty transaction in case the peer broadcasts an old revoked state.

Key Changes:
 - Added new params to stub_chan() to accomodate shachain, basepoints, opener, and remote_to_self_delay
 - Check if any field is NULL inside scb_chan->tlvs and assign them appropriately
2025-02-22 11:51:54 -06:00
Aditya Sharma
fe02d2f1c5 scb_wire: Define new subtype 'modern_scb_chan' with 'scb_tlvs'
We define a new subtype 'modern_scb_chan' and a new tlvtype 'scb_tlvs' which includes
all the relevant information to create a penalty transaction when the peer tries to cheat.

Key Changes:
 - Rename the old format to 'legacy_scb_chan' and define a new type 'modern_scb_chan'
 - Include TLVs to 'modern_scb_chan'
 - Create a new msgtype 'static_chan_backup_with_tlvs'
 - Modify 'struct channel' to include 'struct modern_scb_chan'
 - Add these two types to 'varsize_types' in generate.py
2025-02-22 11:51:54 -06:00
Aditya Sharma
6df6789744 Enable Length-Prefixed TLVs through Generator
This change allows adding a length prefix to a serialized TLV. It will
be particularly useful for serializing all 'scb_chan' entries in
the 'emergency.recover' file.

Key Changes:
 - Removed the need to loop in towire_tlv and fromwire_tlv, so the if conditions have been modified accordingly.
 - During serialization, the length of the TLV is calculated before appending it, and it is stored in a temporary variable.
 - For fromwire_tlv, only a simple length adjustment is required, and no loop is needed here either.
2025-02-22 11:51:54 -06:00
Aditya Sharma
39f63eb27f tools/gen: Enable Subtypes to have TLVStreams
This change will allow subtypes in wiregen files to have tlvstreams.
Shifting tlv structs above subtypes in header_template is done to prevent
forward declaration.

Since generate-wire prepends 'tlv_' in tlvname, we
have to modify fromwire_subtype_field and towire_subtype_field in
impl_template to accommodate this.

Changelog-Added: This PR would turn our peers into watchtower and enable SCB to create penalty txn.
2025-02-22 11:51:54 -06:00
Alex Myers
5b83eff5d9 pytest: update examples generation for listpeerchannels
with fixed our/their_max_htlc_value_in_flight_msat values

suggested by @ShahanaFarooqui
2025-02-21 17:03:36 -06:00
Rusty Russell
a6e476a73b pytest: test sql deprecated field (now we have one!).
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2025-02-21 17:03:36 -06:00
Lagrang3
35f899a588 fetch max total htlc value from listpeerchannel
The parameter max_htlc_value_in_flight_msat stablished by peers on
channel opening (BOLT02) can now be retrived from the
gossmods_from_listpeerchannels API.

Adapted the corresponding callback functions in renepay and askrene to
take into account that value as a constraint to the value we can send
through a channel.

Changelog-Add: fetch max_htlc_value_in_flight_msat from gossmods_listpeerchannels API

Signed-off-by: Lagrang3 <lagrang3@protonmail.com>
2025-02-21 17:03:36 -06:00
Rusty Russell
afb54ff8e8 lightningd: actually deprecate the listpeerchannels field.
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2025-02-21 17:03:36 -06:00
Lagrang3
fe4d5036c2 add max_htlc_value_in_flight_msat to listpeerchan
Changelog-Added: JSON-RPC: `listpeerchannels` new output fields `their_max_total_htlc_out_msat` and `our_max_total_htlc_out_msat` as the value of `max_htlc_value_in_flight` (as of BOLT02) set by the local and remote nodes on channel creation.

Changelog-Deprecated: JSON-RPC: `listpeerchannels` value `max_total_htlc_in_msat`: use `our_max_total_htlc_out_msat` instead to follow spec naming convention.
2025-02-21 17:03:36 -06:00
Rusty Russell
0df3c5869a plugins/sql: allow deprecated field access if wildcards are used.
Otherwise, deprecating a field causes SELECT * to fail:

```
>       l1.rpc.sql(f"SELECT * FROM peerchannels;")
...
>           raise RpcError(method, payload, resp['error'])
E           pyln.client.lightning.RpcError: RPC call failed: method: sql, payload: ('SELECT * FROM peerchannels;',), error: {'code': -1, 'message': 'query failed with access to peerchannels.max_total_htlc_in_msat is prohibited (Deprecated column table peerchannels.max_total_htlc_in_msat)'}
```

So if they use a wildcard, allow access: though "SELECT *" is fraught,
"COUNT(*)" is perfectly legit.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2025-02-21 17:03:36 -06:00
ShahanaFarooqui
37828b556a doc: Add enableoffer in makefile
The `enableoffer` JSON schema is present, but it is not included in the `GENERATE_MARKDOWN` list within the Makefile. This resulted into missing `.7` and `.7.md` files, leading to missing manpage and the documentation portal page.

Changelog-None.
2025-02-21 14:12:18 -06:00
daywalker90
121bec5709 pyln-testing: on cln 24.02.2 and earlier use log-level=debug
Changelog-None
2025-02-21 08:35:50 -06:00
daywalker90
119be76136 pyln-testing: set autoconnect-seeker-peers only in supported cln 24.11+
Changelog-None
2025-02-21 08:35:50 -06:00
Rusty Russell
da793e66b9 xpay: rename payment_failed to payment_give_up
Eduardo points out that payment_failed kind of over-promises: it may
actually not fail the payment now (with slow mode).

It's more an indiciation that we're not trying any more payment parts,
so rename it to payment_give_up.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2025-02-20 20:22:54 -06:00
Rusty Russell
43e59a6774 pytest: test xpay gracefully handles failure after success.
We can create this scenario by having one path force close.  We take
the opportunity to log this, even in non-slow-mode, since it's interesting
(not our bug, but someone just lost money!).

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2025-02-20 20:22:54 -06:00
Rusty Russell
f168cb5949 xpay: add xpay-slow-mode to force waiting for all parts before returning.
This was requested by Michael of Boltz; it's mainly useful if you plan to
try failed payments on a *different* node.  In that case, there's a
theoretical possibility that slow parts of this payment could combine with
that from a different node and overpay.

We don't allow this from the same node, already.

Changelog-Added: xpay: `xpay-slow-mode` makes xpay wait for all parts of a payment to complete before returning success or failure.
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2025-02-20 20:22:54 -06:00
Rusty Russell
db1e26eb67 xpay: refactor payment_succeeded.
1. Don't rely on the current attempt, make caller calculate total.
2. Save preimage inside attempt, for slow mode.
3. Hoist it higher in the file.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2025-02-20 20:22:54 -06:00
Alex Myers
a79dd4ae5f pyln-client: test dev version
Changelog-Changed: pyln-testing is now compatible with older versions of Core Lightning.
2025-02-20 19:40:07 -06:00
Erik De Smedt
dac51930e8 Use check_output instead of run
This is shorter and more readable

Suggested-By: @cdecker
2025-02-20 19:40:07 -06:00
Erik De Smedt
98ac15249e NodeVersion: Fix comparision in CI
When tests CI on occur the version number has the following shape "1a86e50-modded".
We will always assume this is the latest version to make the version
checks pass
2025-02-20 19:40:07 -06:00
Erik De Smedt
752a92130e Print proper error when version comparision fail 2025-02-20 19:40:07 -06:00
Erik De Smedt
50c9dc3095 pyln-testing: Fix compatiblity with old versions 2025-02-20 19:40:07 -06:00
Erik De Smedt
df5d081ed2 Refactor: Provide lightningd in constructor
The fixtures in `tests/fixtures.py` modifies the path to
`lightningd/lightningd`.

I've adapted `pyln-testing` to accept an executable in the constructor.
This approach is more transparant and allows us to use the executable
path to query the version in the constructor.
2025-02-20 19:40:07 -06:00
Erik De Smedt
8e16cb1a16 Support to query version in pyln-client
Introduce a `NodeVersion`-class into `pyln.client`.
This can be used to test if `lighningd` supports the required
functionality
2025-02-20 19:40:07 -06:00
fanquake
e8c8fd4195 docs: update bitcoin core install docs
Changelog-None

Signed-off-by: fanquake <fanquake@gmail.com>
2025-02-20 19:04:22 -06:00
Rusty Russell
d15f5a9b3b lightningd: don't even transiently try to connect to private nodes if --dev-no-reconnect-private.
Christian reported that this flag doesn't work on restart.

Indeed, it made us attempt *transient* rather than *persistent*
connections, but we still told connectd to connect.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
Changelog-Fixed: connectd: `dev-no-reconnect-private` is respected on restart.
2025-02-21 11:24:35 +10:30
Rusty Russell
a4e64fac58 pytest: write a test for --dev-no-reconnect-private.
Indeed it fails.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2025-02-21 11:24:35 +10:30
Rusty Russell
6d142dfad2 pytest: add multiline help test.
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2025-02-20 14:37:28 +10:30
Rusty Russell
44093f09c3 lightning-cli: use human_readable for help messages (unescapes \n for us).
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
Changelog-Changed: lightning-cli: `help` messages using new-lines is now printed properly, enhancing readability and consistency.
2025-02-20 14:37:28 +10:30
Rusty Russell
ca0c9e63ad lightningd: insert "raw" (unescaped) help messages from commands.
So if they want a \n in usage, they can have it.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2025-02-20 14:37:28 +10:30
Nishant Bansal
f524f1172f pyln-client: use \n as line separator in lightning-cli help
Changelog-Changed: Interpret \n as the line separator in plugins to enhance the readability of lightning-cli help.

Signed-off-by: Nishant Bansal <nishant.bansal.282003@gmail.com>
[ Modified to use \n not | --RR ]
2025-02-20 14:37:28 +10:30
Nishant Bansal
eafb6d8c63 pyln-client: remove unused doc variable from plugin.
The `doc` variable was being initialised and processed but not used anywhere.
Changelog-None

Signed-off-by: Nishant Bansal <nishant.bansal.282003@gmail.com>
2025-02-20 14:37:28 +10:30
Lagrang3
f5c8934e22 xpay: reduce log entries on rpc_command hook
Don't print unnecessary log entries every time we receive an rpc_command
hook event. Only log when `pay` is called.

Changelog-None

Signed-off-by: Lagrang3 <lagrang3@protonmail.com>
2025-02-19 16:17:44 -06:00
ShahanaFarooqui
3649a54f04 docs: Lock example values to avoid unnecessary updates in schemas
Changelog-None.
2025-02-19 15:51:44 -06:00
Alex Myers
26359e4c8c pytest: address flakes from blinded paths in bolt12 offers
Following 6e4ff6a, nodes now check for their public address and
generate a blinded path for invoices if the address is not advertized.
This breaks several of the tests where the blinded path is expected
to have the entrypoint be the node itself.

Changelog-None
2025-02-19 10:25:51 -06:00
Rusty Russell
8fedb26e6e pytest: fix test_xpay_bolt12_no_mpp
When we merged blinded paths for nodes with no address
(6e4ff6a7d2), this test
broke.  We need to prevent that, otherwise:

```
>       assert ret['successful_parts'] == 2
E       assert 1 == 2

tests/test_xpay.py:677: AssertionError
```

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2025-02-17 17:12:19 +10:30
Erick λ
38b9cb94d3 docs: fix JSON indentation in 'connect' example Changelog-None 2025-02-17 15:59:12 +10:30
daywalker90
5e0a25bca9 cln-grpc, clnrest: workaround for logging before shutdown
Changelog-Fixed: cln-grpc and clnrest errors that cause them to stop will now log
2025-02-14 14:58:00 -06:00
Rusty Russell
4bb7b49f0a pytest: test that we indeed do MPP even if not advertized.
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2025-02-14 22:17:21 +10:30
Rusty Russell
d881c3cf3e offers: fix incorrect name for field.
It wasn't documented, and hopefully nobody was using it.

Changelog-Fixed: `decode` for bolt12 invoices "features" field renamed to "invoice_features" (as documentation said)
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2025-02-14 22:17:21 +10:30
Rusty Russell
e2be010cbb offers: correctly advertize MPP in invoice features.
Turns out we weren't wiring them through!  And libplugin wasn't reading them anyway.

Changelog-Fixed: lightningd: tell plugins our bolt12 features (so our bolt12 invoices explicitly allow MPP).
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2025-02-14 22:17:21 +10:30
Rusty Russell
c718e35359 xpay: in future, don't MPP to pay bolt12 invoices unless invoice explicitly says so.
We don't want to enable this yet, since we only just fixed CLN this release!

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2025-02-14 22:17:21 +10:30
Rusty Russell
7577af0d59 common: if something isn't deprecated yet, it's always ok.
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2025-02-14 22:17:21 +10:30
Rusty Russell
731aa497c3 offers: don't call create_invoicereq twice.
We ignored the second one, but still it's unnecessary.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2025-02-14 22:17:21 +10:30
Rusty Russell
4ed709f9ec xpay: avoid MPP if invoice does not allow it.
This is deeply annoying, and we may have to support this properly
(using a separate algorithm entirely) if other implementations don't
fix their crap.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
Changelog-Fixed: Plugins: xpay: suppress multi-part payment if invoice doesn't allow it (please, fix your nodes!)
2025-02-14 22:17:21 +10:30
Rusty Russell
461eb2eddb askrene: remove all small channels if there's no MPP support.
This is an inefficient hack.  Can you tell I really didn't want to
implement this?  MPP was finalized in 2018 FFS.

We do this by adding another "auto" layer, which removes all too-small
channels, and then makes our MPP node pile all the funds into the largest
channel it chooses.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2025-02-14 22:17:21 +10:30
Rusty Russell
5b74e98201 pytest: test that xpay doesn't use MPP if invoice doesn't permit it.
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2025-02-14 22:17:21 +10:30
Rusty Russell
6d961f6b13 devtools: allow encode with 9 flag (for features).
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2025-02-14 22:17:21 +10:30
Rusty Russell
91d7394175 askrene: don't include impossible channels in the MCF graph.
In particular, if the total amount we're sending is less than the minimum amount
the channel insists on, we can eliminate it.

This fixes the problem that we're really trying to send a de-minumus
amount (rather than the more obscure case where we divide the amount
and then it is below the minimum).

After trying several other approaches, this was by far the cleanest!

Reported-by: https://github.com/JssDWt
Fixes: https://github.com/ElementsProject/lightning/issues/8045
Changelog-Fixed: xpay: don't simply give up if our total amount is less than htlc_minimum_msat on some channel.
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2025-02-14 15:18:48 +10:30
Rusty Russell
38b9df44b2 pytest: test that askrene doesn't simply give up if we are below htlc_minimum.
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2025-02-14 15:18:48 +10:30
Rusty Russell
6e4ff6a7d2 offers: add a blinded path if we have no advertized address.
Suggested-by: Matt Corallo
Fixes: https://github.com/ElementsProject/lightning/issues/7806
Changelog-Changed: Offers: we will use a blinded path if we have no advertized address (so payers wouldn't be able to connect directly).
2025-02-14 14:18:29 +10:30
Rusty Russell
f806b26734 Makefile: update CLN_NEXT_VERSION.
I should have done this immediately after last release :(.

This turns various things off by default, even if deprecated APIs are enabled.

We remove the test of the to-be-removed params.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
Changelog-Deprecated: Config: `rest-port`, `rest-protocol`, `rest-host` and `rest-certs` disabled by default (use clnrest-*, or `i-promise-to-fix-broken-api-user=rest-port.clnrest-prefix` etc and PLEASE REPORT if you need this!)
Changelog-Deprecated: Config: `max-locktime-blocks` disabled by default (use `i-promise-to-fix-broken-api-user=max-locktime-blocks` and PLEASE REPORT if you need this!)
2025-02-13 21:15:45 -06:00
Rusty Russell
2ffe07b0df lightningd: make i-promise-to-fix-broken-api-user an early option.
Otherwise it doesn't work to fix up other options!

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2025-02-13 21:15:45 -06:00
Rusty Russell
e3c36988ea pytest: add override options to prepare for default removal of rest-port/rest-host options.
Otherwise this test breaks when we change CLN_NEXT_VERSION.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2025-02-13 21:15:45 -06:00
Rusty Russell
2b3b7fde2c pytest: expect complaints when we use deprecated commando-runes commands.
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2025-02-13 21:15:45 -06:00
Rusty Russell
d18f564324 pytest: stop using deprecated commando_rune commands.
These are about to start logging warnings, so use modern versions for tests
which aren't explicitly about testing obsolete ones.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2025-02-13 21:15:45 -06:00
Rusty Russell
e81a50e551 pytest: fix change in error msg from latest bitcoind master.
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2025-02-13 21:15:45 -06:00
Rusty Russell
4e568e4f0d testing: don't try to valgrind clnrest, it's Rust.
This happened in CI:

```
algrind error file: valgrind-errors.16800
==16800== Thread 4 tokio-runtime-w:
==16800== Conditional jump or move depends on uninitialised value(s)
==16800==    at 0x2466BF: _ZN175_$LT$axum..middleware..from_fn..FromFn$LT$F$C$S$C$I$C$$LP$T1$C$T2$C$T3$RP$$GT$$u20$as$u20$tower_service..Service$LT$http..request..Request$LT$axum_core..body..Body$GT$$GT$$GT$4call28_$u7b$$u7b$closure$u7d$$u7d$17h4cc36de5dd56d9feE.llvm.119371497468325184 (in /home/runner/work/lightning/lightning/plugins/clnrest)
==16800==    by 0x57BFFA: <axum::middleware::from_fn::ResponseFuture as core::future::future::Future>::poll (in /home/runner/work/lightning/lightning/plugins/clnrest)
==16800==    by 0x37312B: <futures_util::future::future::map::Map<Fut,F> as core::future::future::Future>::poll (in /home/runner/work/lightning/lightning/plugins/clnrest)
==16800==    by 0x372D8D: <futures_util::future::future::map::Map<Fut,F> as core::future::future::Future>::poll (in /home/runner/work/lightning/lightning/plugins/clnrest)
==16800==    by 0x372F59: <futures_util::future::future::map::Map<Fut,F> as core::future::future::Future>::poll (in /home/runner/work/lightning/lightning/plugins/clnrest)
==16800==    by 0x373A88: <tower::util::map_response::MapResponseFuture<F,N> as core::future::future::Future>::poll (in /home/runner/work/lightning/lightning/plugins/clnrest)
==16800==    by 0x32100D: <tower::util::oneshot::Oneshot<S,Req> as core::future::future::Future>::poll (in /home/runner/work/lightning/lightning/plugins/clnrest)
==16800==    by 0x38E326: _ZN91_$LT$axum..routing..route..RouteFuture$LT$E$GT$$u20$as$u20$core..future..future..Future$GT$4poll17h3f11114fc5dd51f8E.llvm.194396656150191000 (in /home/runner/work/lightning/lightning/plugins/clnrest)
==16800==    by 0x372315: <futures_util::future::future::map::Map<Fut,F> as core::future::future::Future>::poll (in /home/runner/work/lightning/lightning/plugins/clnrest)
==16800==    by 0x372C05: <futures_util::future::future::map::Map<Fut,F> as core::future::future::Future>::poll (in /home/runner/work/lightning/lightning/plugins/clnrest)
==16800==    by 0x371A15: <futures_util::future::future::map::Map<Fut,F> as core::future::future::Future>::poll (in /home/runner/work/lightning/lightning/plugins/clnrest)
==16800==    by 0x373A48: <tower::util::map_response::MapResponseFuture<F,N> as core::future::future::Future>::poll (in /home/runner/work/lightning/lightning/plugins/clnrest)
==16800==
```

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2025-02-13 20:46:11 -06:00
Lagrang3
a2a186ff29 renepay: change the groupid selection
Searches the first unused groupid and uses that number for the current
payment attempt.
We previously used the highest value of used groupid + 1, which breaks
in a few corner cases.

Changelog-None

Signed-off-by: Lagrang3 <lagrang3@protonmail.com>
2025-02-13 19:16:21 -06:00
Lagrang3
0e98426f02 renepay: names by convention
Change functions json_pay and json_paystatus to json_renepay
and json_renepaystatus to match the conventional naming.
This is helpful for grep searches.

Changelog-None

Signed-off-by: Lagrang3 <lagrang3@protonmail.com>
2025-02-13 19:16:21 -06:00
Lagrang3
ddb62a1114 renepay: bugfix: read groupids as u64
Changelog-Fixed: renepay: read groupids as u64 integers.

Signed-off-by: Lagrang3 <lagrang3@protonmail.com>
2025-02-13 19:16:21 -06:00
Rusty Russell
df24568143 pytest: remove test_slow_startup_many_addresses
As I suspected, benchmark tests like this are too unreliable under CI.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2025-02-13 15:42:51 -06:00
Rusty Russell
645b202222 wallet: use htable in wallet_add_onchaind_utxo.
On lookup, we update the htable if any new addresses have been added.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
Changelog-Fixed: lightningd: startup time vastly improved for large nodes with pending closes and many bitcoin addresses.
2025-02-13 15:42:51 -06:00
Rusty Russell
44ff4fe5fa wallet: create htable to store scriptpubkeys for issued indexes.
For now we don't actually update it; that's next patch.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2025-02-13 15:42:51 -06:00
Rusty Russell
d7ad8af27c wallet: wallet_get_addrtype should tell caller it has no info.
Turns out we don't actually use this, so easy to change the function.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2025-02-13 15:42:51 -06:00
Rusty Russell
ca785bac06 wallet: re-add ADDR_P2SH_SEGWIT type to enum addrtype
It was long obsoleted, and never appears in the DB, but we do still have
to handle old ones in the code.

We removed it from the enum in
f342630b92 (v24.02) after deprecating it
in 23.02.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2025-02-13 15:42:51 -06:00
Rusty Russell
c13756d2c5 pytest: test for slow start when closing tx and large number of addresses.
From Whitslack's "startup takes 15 minutes" bug report, we can see
that wallet_can_spend is extremely slow.  We exacerbate this by setting a large
bip32_max_index:

```
    91.29%     0.02%  lightningd       lightningd                 [.] wallet_can_spend
            |          
             --91.27%--wallet_can_spend
                       |          
                       |--47.81%--scriptpubkey_p2tr_derkey
                       |          |          
                       |          |--42.80%--scriptpubkey_p2tr
...
                       |--42.16%--bip32_key_from_parent
```

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2025-02-13 15:42:51 -06:00
ShahanaFarooqui
6bcc05ac34 pyln-testing: Fix for disabled schema check
In a previous [commit](https://github.com/ElementsProject/lightning/pull/8065/commits), I mistakenly removed the `lightning-` replacement logic from the base name also. This commit restores that functionality to re-enable schema checks.

Changelog-None.
2025-02-13 15:58:22 +10:30
nicolas.dorier
36b3883215 Fix: getblockfrompeer was always requesting block to the first peer
Changelog-Fixed: getblockfrompeer was always requesting block to the first peer
2025-02-12 11:03:14 -06:00
Lagrang3
dfd9e815ba lightning-cli: fix the access to man pages
Changelog-Fixed: lightning-cli: access to man pages from the installed directory.

Signed-off-by: Lagrang3 <lagrang3@protonmail.com>
2025-02-12 14:20:56 +10:30
Lagrang3
37150c1f49 renepay: add test_unannounced
Changelog-None.

Signed-off-by: Lagrang3 <lagrang3@protonmail.com>
2025-02-12 13:36:06 +10:30
Lagrang3
552bb1c88c renepay: decode error onion
When paying with injectpaymentonion we need to manually decode the error
from the onion.

Changelog-None.

Signed-off-by: Lagrang3 <lagrang3@protonmail.com>
2025-02-12 13:36:06 +10:30
Lagrang3
158fb91062 renepay: resolve self payments with fake node
Always use a fake destination node, the self-payments are no longer a
corner case for the routing problem in this way. Also it is ok for
get_routes to return routes with zero length.

Changelog-None.

Signed-off-by: Lagrang3 <lagrang3@protonmail.com>
2025-02-12 13:36:06 +10:30
Lagrang3
ef67fe335d renepay: use injectpaymentonion
Use injectpaymentonion for payments with |routes|=0,
ie. self-payments and blinded paths where our node is
the first node in the blinded path.

Changelog-None.

Signed-off-by: Lagrang3 <lagrang3@protonmail.com>
2025-02-12 13:36:06 +10:30
Lagrang3
3fbf73cde5 renepay: simplify rpc error callback functions
Changelog-None.

Signed-off-by: Lagrang3 <lagrang3@protonmail.com>
2025-02-12 13:36:06 +10:30
Lagrang3
92863e30a5 renepay: more informative renesendpay error reply
Changelog-None.

Signed-off-by: Lagrang3 <lagrang3@protonmail.com>
2025-02-12 13:36:06 +10:30
Lagrang3
3ae8b5e969 renepay: don't fail parsing sendpay error
Changelog-None.

Signed-off-by: Lagrang3 <lagrang3@protonmail.com>
2025-02-12 13:36:06 +10:30
Lagrang3
74effa31d2 renepay: make self payments with renesendpay
Changelog-None.

Signed-off-by: Lagrang3 <lagrang3@protonmail.com>
2025-02-12 13:36:06 +10:30
Lagrang3
a04010c871 renepay: collect shared secrets
Collect the shared secrets when making a payment request.
We would need this if we use injectpaymentonion instead of sendonion.

Changelog-None.

Signed-off-by: Lagrang3 <lagrang3@protonmail.com>
2025-02-12 13:36:06 +10:30
Lagrang3
d7fba2d75b renepay: add test for simple offer
Changelog-None.

Signed-off-by: Lagrang3 <lagrang3@protonmail.com>
2025-02-12 13:36:06 +10:30
Lagrang3
6c165e6d9c renepay: refactor create_onion
Refactor create_onion function, now we could use the same function to
build onions for sendonion and injectpaymentonion.

Changelog-None.

Signed-off-by: Lagrang3 <lagrang3@protonmail.com>
2025-02-12 13:36:06 +10:30
Lagrang3
843c0b7d8c renepay: add function blinded path to json
Changelog-None.

Signed-off-by: Lagrang3 <lagrang3@protonmail.com>
2025-02-12 13:36:06 +10:30
Lagrang3
90789287ff renepay: skip test_previous_sendpays
sendonion RPC does not allow to set the total amount in lightningd's
wallet, therefore it mixing sendpay and sendonion payment parts would
not work. That means for the time being we cannot complete a payment
initialized with sendpay until we add a total_amount parameter to
sendonion.

Changelog-None.

Signed-off-by: Lagrang3 <lagrang3@protonmail.com>
2025-02-12 13:36:06 +10:30
Lagrang3
47061f15ce renepay: fix error handling
Fix error handling since we moved from sendpay to sendonion rpc.
With sendonion once a route fails we don't get the scid and node_id that
failed along the route, so we have to deduce those from our own internal
data.

Changelog-None

Signed-off-by: Lagrang3 <lagrang3@protonmail.com>
2025-02-12 13:36:06 +10:30
Lagrang3
5672c29952 renepay: use our own sendpay rpc
Use renesendpay to send the payment allowing to pay to BOLT12 invoices
from a higher level interface.

Changelog-Add: renepay: Add support for BOLT12 payments

Signed-off-by: Lagrang3 <lagrang3@protonmail.com>
2025-02-12 13:36:06 +10:30
Lagrang3
6ab3bbbac5 renepay: change of variable name for clarity
Changing route.amount to route.amount_deliver
for clarity. This variable hold the value that
the route delivers to destination.

Changelog-None

Signed-off-by: Lagrang3 <lagrang3@protonmail.com>
2025-02-12 13:36:06 +10:30
Lagrang3
5b7f0eacf4 renepay: add rpc that replaces sendpay
Add an rpc to renepay that is similar to sendpay that
handles BOLT11 and BOLT12 payments.
This is not the most elegant solution but it is a workaround
until we implement it into lightningd which has more development
friction.

Changelog-None.

Signed-off-by: Lagrang3 <lagrang3@protonmail.com>
2025-02-12 13:36:06 +10:30
Lagrang3
af66bf2235 renepay: enable routing through blinded paths
Enable routing through blinded paths using fake channels in local
gossmods.

Changelog-None

Signed-off-by: Lagrang3 <lagrang3@protonmail.com>
2025-02-12 13:36:06 +10:30
Lagrang3
1311223da5 renepay: parse bolt12 invoices
A first step towards supporting bolt12 invoices and blinded paths.

Changelog-None

Signed-off-by: Lagrang3 <lagrang3@protonmail.com>
2025-02-12 13:36:06 +10:30
gudnuf
4a280148f1 single plugin_notification_serialize function 2025-02-12 12:54:10 +10:30
gudnuf
61482e5f45 new notifications: plugin_stopped and plugin_started
[Added version tag into documentation, to show it was added in 25.02 --RR]
Changelog-Added: Plugins: new nofitications `plugin_stopped` and `plugin_started`
2025-02-12 12:54:10 +10:30
Rusty Russell
c3362b057c BOLT12: remove -offers from bolt12 quotes, update them.
Typo fixes and wording changes.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2025-02-11 20:19:01 -06:00
Rusty Russell
c22cc11af5 fetchinvoice: allow user to specify bip353 name corresponding to how they got offer.
Changelog-Added: JSON-RPC: `fetchinvoice` BIP 353 name support (`bip353`).
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2025-02-11 20:19:01 -06:00
Rusty Russell
22a2366901 offers: enforce restrictions in incoming bip353 name fields.
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2025-02-11 20:19:01 -06:00
Rusty Russell
ba3e85bb43 decode: handle new bip353 fields.
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2025-02-11 20:19:01 -06:00
Rusty Russell
3d8238fef9 bolt12: add inv invreq_bip_353_name field to invoice.
All things are supposed to be mirrored from invoice_request into invoice.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2025-02-11 20:19:01 -06:00
Rusty Russell
7b00e610f6 wire: extract bolt12 by default, now it's merged.
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2025-02-11 20:19:01 -06:00
Rusty Russell
c93ff8e2da wire: update to bolt version which has offers included.
We don't need our patch to add the fields any more.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2025-02-11 20:19:01 -06:00
Rusty Russell
7d62129dbf wire: update bolts which include sciddir_or_pubkey in blinded path.
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2025-02-11 20:19:01 -06:00
Rusty Russell
77eef3b62e lightningd: update bolts to clarify channel_update timing.
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2025-02-11 20:19:01 -06:00
Rusty Russell
fa188c80ca common: update bolts to include hash value in bolt11 test vectors.
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2025-02-11 20:19:01 -06:00
Rusty Russell
b879cb475f common: update bolt to neaten pubkey descriptions.
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2025-02-11 20:19:01 -06:00
Rusty Russell
f20bea605b wire: fix extracted files.
Changes were made to the wire files manually, but we're supposed to edit the
patches so they can be reproduced.
2025-02-11 20:19:01 -06:00
Alex Myers
c9b01b60a0 unit-tests: cleanup traces after testing
Otherwise it appears to be a leak:

==612637== 11,264 bytes in 1 blocks are still reachable in loss record 1 of 1
==612637==    at 0x484D953: calloc (in /usr/libexec/valgrind/vgpreload_memcheck-amd64-linux.so)
==612637==    by 0x1301F2: trace_init (trace.c:153)
==612637==    by 0x13065D: trace_span_start (trace.c:263)
==612637==    by 0x173968: db_open_ (utils.c:367)
==612637==    by 0x17AE43: create_test_wallet (run-wallet.c:1313)
==612637==    by 0x17C726: test_shachain_crud (run-wallet.c:1548)
==612637==    by 0x18300E: main (run-wallet.c:2329)

Changelog-None
2025-02-11 19:16:16 -06:00
Alex Myers
39753f1fd6 pytest: Address race condition in test_gossip_jsonrpc
In the time it takes connectd to flush the log message for
, gossipd can already have
the announcement sent.

lightningd-1 2025-02-11T15:26:06.745Z DEBUG 022d223620a359a47ff7f7ac447c85c46c923da53389221a0054c11c1e3ca31d59-channeld-chan#1: peer_in WIRE_ANNOUNCEMENT_SIGNATURES
lightningd-2 2025-02-11T15:26:06.887Z DEBUG 0266e4598d1d3c415f572a8488830b60f7e744ed9235eb0b1ba93283b315c03518-channeld-chan#1: peer_in WIRE_ANNOUNCEMENT_SIGNATURES
lightningd-1 2025-02-11T15:26:06.897Z TRACE gossipd: Received node_announcement for node 0266e4598d1d3c415f572a8488830b60f7e744ed9235eb0b1ba93283b315c03518
lightningd-1 2025-02-11T15:26:06.915Z DEBUG 022d223620a359a47ff7f7ac447c85c46c923da53389221a0054c11c1e3ca31d59-connectd: peer_out WIRE_ANNOUNCEMENT_SIGNATURES

Changelog-None
2025-02-11 19:16:16 -06:00
Rusty Russell
1820423cbc common: fix memcpy error in Fischer-Yates shuffle.
Reported by Grubles on ARM64:

```
VALGRIND=1 valgrind -q --error-exitcode=7 --track-origins=yes --leak-check=full --show-reachable=yes --errors-for-leak-kinds=all common/test/run-tal_arr_randomize > /dev/null
==151138== Source and destination overlap in memcpy(0x4d69f08, 0x4d69f08, 8)
==151138==    at 0x48CB68C: __GI_memcpy (vg_replace_strmem.c:1147)
==151138==    by 0x41B50B: tal_arr_randomize_ (pseudorand.c:84)
==151138==    by 0x41BB07: main (run-tal_arr_randomize.c:166)
==151138==
make: *** [Makefile:750: unittest/common/test/run-tal_arr_randomize] Error 7
```

It is correct: you can't overlap src and dst in memcpy.  It *probably* works in
this case, but it's undefined!

Fixes: https://github.com/ElementsProject/lightning/issues/7030
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2025-02-11 16:54:08 -06:00
Rusty Russell
d554206d7e gossipd: fix bogus message when dying channel is pruned.
```
2025-01-23T12:31:52.528Z DEBUG   gossipd: Pruning channel 839050x1246x0 from network view (ages 1736283379 and 1737600120)
2025-01-27T00:32:01.631Z DEBUG   gossipd: Pruning channel 839050x1246x0 from network view (ages 0 and 1737686520)
2025-01-27T00:50:05.998Z **BROKEN** gossipd: Dying channel 839050x1246x0 already deleted?
```

Easiest not to prune in this case.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2025-02-11 15:11:47 -06:00
Rusty Russell
2b4b1479ed gossipd: check that gossmap code sees updates from gossip_store writes.
After analyzing various weird cases where we ended up with duplicate
gossip_store entries, it could be explained by us not fully processing
the gossip store.

It's not clear that my assumptions that we would always see our own writes
are true: technically this may require an fsync().  So we now add the
check, and do an fsync and try again.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
Changelog-Fixed: gossipd: more sanity checks that we are correctly updating the gossip_store file.
2025-02-11 15:11:47 -06:00
Rusty Russell
8156c83e11 gossipd: check that we are always appending.
We had at least one report of overwriting the gossip_store file at
offset 1.  Make sure this doesn't happen.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2025-02-11 15:11:47 -06:00
Rusty Russell
769ccaa4c3 gossipd: correctly process dying channels.
Found by inspection.  Minor bug, since we'll catch it on the next block,
but annoying.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2025-02-11 15:11:47 -06:00
Rusty Russell
1df1300cc9 gossip_store: don't need to check for truncated amounts.
That's actually caught by the gossmap load now.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2025-02-11 15:11:47 -06:00
Rusty Russell
9d98740e18 gossmap: stricter checks when gossipd itself loads the gossip_store.
This means we will correctly reset the store if it has redundant
records, for example.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2025-02-11 15:11:47 -06:00
Rusty Russell
4f2a7039c6 gossipd: put gossip_store pointer inside gossmap_manage.
It's actually the only one that uses it.  We also tweak the way
gossip_store handles failure: gossmap_manage now tells it when to
reset the corrupted store.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2025-02-11 15:11:47 -06:00
Rusty Russell
e440799b5e devtools: have dump-gossipstore print malformed warnings to stdout.
If they go to stderr, you can't associate them with the record they're
talking about.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2025-02-11 15:11:47 -06:00
Rusty Russell
05bc4ca5f3 gossmap: use mmap directly to check checksums.
Instead of making a copy.

To measure the performance impact, I timed
tests/test_askrene.py::test_real_biases on my laptop.

	No checksum check: 194.52s
	Copying for checksum check: 202.81s
	Zero-copy checksum check: 194.40s

But these numbers proved noisy.  Still, doesn't hurt.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2025-02-11 15:11:47 -06:00
Rusty Russell
4b5e5b27ae gossmap: check checksums.
We assume if it's incorrect, we simply need to wait.  If this proves incorrect,
we will see a stream of BROKEN log messages.

To measure the performance impact, I timed
tests/test_askrene.py::test_real_biases on my laptop.

	Before: 194.52s
	After: 202.81s

So it's marginal.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2025-02-11 15:11:47 -06:00
Rusty Russell
307dbe3e62 tests: put proper checksums into test gossip_store files.
We're about to test them in gossmap.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2025-02-11 15:11:47 -06:00
Rusty Russell
5e2f6c5028 gossmap: don't stop reading if we hit a redundant channel_announce.
While this shouldn't happen, it does (pending other fixes), and we stop reading the
gossip store until next time.  The result is partial gossip, demonstrated beautifully
by NicolasDorier's report:

```
lightning_gossipd: gossmap: redundant channel_announce for 864063x1306x1, offsets 1272259 and 1784859!"
```

Gossipd stalld there and don't make more progress.  So gossipd itself
doesn't see the entire gossip_store.

Then things get really batshit:

```
2025-02-04T05:53:28.582Z DEBUG   gossipd: Store compact time: 1429910 msec
```

This took 1429 seconds to process.  Why?

Because it hasn't been processing the gossip store fully, gossipd kept adding "new" records to the end:

```
2025-02-04T05:53:28.583Z DEBUG   gossipd: gossip_store: Read 62716143/1739952/5158256/0 cannounce/cupdate/nannounce/delete from store in 31634458462 bytes, now 31634458440 bytes (populated=true)
```

It has 31GB of gossip in there!  No wonder it took so long...

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
Fixes: https://github.com/ElementsProject/lightning/issues/8035
Changelog-Fixed: gossipd: corruption in the gossip_store could cause ever-longer startup times and no gossip updates.
2025-02-11 15:11:47 -06:00
Rusty Russell
fdfc7ce62f gossmap: add (and use) logging hook.
Default goes to stderr for LOG_UNUSUAL and higher.

We have to whitelist more cases in map_catchup so we don't spam the logs
with perfectly-expected (but ignored) messages though.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2025-02-11 15:11:47 -06:00
Rusty Russell
607b14fe12 common/gossmap: remove open-by-fd.
We only use it in one place, and that was simply to share an fd between
gossipd writing and gossipd reading, which may be causing our zfs problem
anyway.

In fact, it fixes a race if we don't have HAVE_PWRITEV.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2025-02-11 15:11:47 -06:00
Rusty Russell
927d062b04 gossmap: don't crash if we hit a zero-length record.
We have a report of this happening under ZFS.  We cannot do much if
this really is a problem where we can't read back what we write, but
this avoids the immediate crash.

Fixes: https://github.com/ElementsProject/lightning/issues/7971
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
Changelog-Fixed: gossmap: occasional crash (at least on ZFS) reading gossip_store.
2025-02-11 15:11:47 -06:00
Rusty Russell
01650ebcd7 gossipd: make sure we never write bad entries.
We have reports of crashes on reading gossip_store, including from gossipd itself!

```
lightning_gossipd: common/gossmap.c:121: map_copy: Assertion `offset + len <= map->map_size' failed.
...
lightning_gossipd: FATAL SIGNAL (version v24.11)
0x6260c41d682a send_backtrace
  common/daemon.c:33
0x6260c41e098b status_failed
  common/status.c:221
0x6260c41e0b41 status_backtrace_exit
  common/subdaemon.c:18
0x6260c41d68b8 crashdump
  common/daemon.c:78
0x70508ea6913f ???
  ???:0
0x70508e8a0d51 ???
  ???:0
0x70508e88a536 ???
  ???:0
0x70508e88a40e ???
  ???:0
0x70508e8996d1 ???
  ???:0
0x6260c41d8b69 map_copy
  common/gossmap.c:121
0x6260c41d8bab map_be16
  common/gossmap.c:142
0x6260c41daa45 map_catchup
  common/gossmap.c:705
0x6260c41dab95 gossmap_refresh_mayfail
  common/gossmap.c:1192
0x6260c41daca6 gossmap_refresh
  common/gossmap.c:1213
0x6260c41cee32 gossmap_manage_get_gossmap
  gossipd/gossmap_manage.c:1314
0x6260c41d0686 gossmap_manage_new_block
  gossipd/gossmap_manage.c:1221
0x6260c41cbfdd new_blockheight
  gossipd/gossipd.c:473
0x6260c41cc363 recv_req
  gossipd/gossipd.c:584
0x6260c41d6b1d handle_read
  common/daemon_conn.c:35
0x6260c43175b5 next_plan
  ccan/ccan/io/io.c:60
0x6260c4317a40 do_plan
  ccan/ccan/io/io.c:422
0x6260c4317af9 io_ready
  ccan/ccan/io/io.c:439
0x6260c4319446 io_loop
  ccan/ccan/io/poll.c:455
0x6260c41cccf4 main
  gossipd/gossipd.c:665
```

This implies that we have a message shorter than 2 bytes, which should never happen.

An audit didn't shed any light, but let's make sure we don't ever write such a thing.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2025-02-11 15:11:47 -06:00
Alex Myers
c060cef546 contrib: startup_regtest.sh linter cleanup
solves check-shellcheck complaints of:
note: Double quote to prevent globbing and word splitting. [SC2086]

Changelog-None
2025-02-11 08:40:29 -06:00
Alex Myers
41b05e14b7 pytest: update test_plugin_slowinit to match longer timeout 2025-02-11 08:40:29 -06:00
Rusty Russell
c8d85acb87 doc: fix missing example update.
In 4e7ba96729 (ightningd: don't kill onchaind
if we are forcing a disconnect.) actually was something which happened
in our generate examples script.

This updates that.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2025-02-11 08:40:29 -06:00
Rusty Russell
043895e2c6 build: fix rust parallel build race.
plugins/Makefile has target/${RUST_PROFILE}/cln-grpc depend on the
generated files via $(MSGGEN_GENALL), but cln-rpc/Makefile adds to
that variable, so needs to be included first.

Here's an example build error:

```
Combining schemas from /home/rusty/lightning-ltest/doc/schemas into /home/rusty/lightning-ltest/contrib/msggen/msggen/schema.json
Created /home/rusty/lightning-ltest/contrib/msggen/msggen/schema.json from 2 files
error: failed to run custom build command for `cln-grpc v0.3.0 (/home/rusty/lightning-ltest/cln-grpc)`

Caused by:
  process didn't exit successfully: `/home/rusty/lightning-ltest/target/debug/build/cln-grpc-95489e3ba33c0ab3/build-script-build` (exit status: 101)
  --- stdout
  cargo:rerun-if-changed=proto/node.proto
  cargo:rerun-if-changed=proto

  --- stderr
  thread 'main' panicked at cln-grpc/build.rs:7:10:
  called `Result::unwrap()` on an `Err` value: Custom { kind: Other, error: "protoc failed: node.proto:134:52: \"AskreneageResponse\" is not defined.\nnode.proto:135:23: \"GetroutesRequest\" is not defined.\nnode.proto:135:50: \"GetroutesResponse\" is not defined.\nnode.proto:136:32: \"AskrenedisablenodeRequest\" is not defined.\nnode.proto:136:68: \"AskrenedisablenodeResponse\" is not defined.\nnode.proto:137:34: \"AskreneinformchannelRequest\" is not defined.\nnode.proto:137:72: \"AskreneinformchannelResponse\" is not defined.\nnode.proto:138:34: \"AskrenecreatechannelRequest\" is not defined.\nnode.proto:138:72: \"AskrenecreatechannelResponse\" is not defined.\nnode.proto:139:34: \"AskreneupdatechannelRequest\" is not defined.\nnode.proto:139:72: \"AskreneupdatechannelResponse\" is not defined.\nnode.proto:140:32: \"AskrenebiaschannelRequest\" is not defined.\nnode.proto:140:68: \"AskrenebiaschannelResponse\" is not defined.\nnode.proto:141:37: \"AskrenelistreservationsRequest\" is not defined.\nnode.proto:141:78: \"AskrenelistreservationsResponse\" is not defined.\nnode.proto:142:32: \"InjectpaymentonionRequest\" is not defined.\nnode.proto:142:68: \"InjectpaymentonionResponse\" is not defined.\nnode.proto:143:18: \"XpayRequest\" is not defined.\nnode.proto:143:40: \"XpayResponse\" is not defined.\nnode.proto:145:33: \"StreamBlockAddedRequest\" is not defined.\nnode.proto:145:74: \"BlockAddedNotification\" is not defined.\nnode.proto:146:40: \"StreamChannelOpenFailedRequest\" is not defined.\nnode.proto:146:88: \"ChannelOpenFailedNotification\" is not defined.\nnode.proto:147:36: \"StreamChannelOpenedRequest\" is not defined.\nnode.proto:147:80: \"ChannelOpenedNotification\" is not defined.\nnode.proto:148:30: \"StreamConnectRequest\" is not defined.\nnode.proto:148:68: \"PeerConnectNotification\" is not defined.\nnode.proto:149:32: \"StreamCustomMsgRequest\" is not defined.\nnode.proto:149:72: \"CustomMsgNotification\" is not defined.\n" }
  note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
make: *** [plugins/Makefile:305: target/debug/cln-grpc] Error 101
make: *** Waiting for unfinished jobs....
```

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2025-02-11 08:40:29 -06:00
Rusty Russell
0e2f4571f2 pytest: fix plugin fail timeout test:
We didn't update this when we extended the timeout to 120 seconds in
ee3133f198 ("lightningd: increase
startup time for plugins to 120 seconds.")

```
    def test_failing_plugins(directory):
        fail_plugins = [
            os.path.join(os.getcwd(), 'contrib/plugins/fail/failtimeout.py'),
            os.path.join(os.getcwd(), 'contrib/plugins/fail/doesnotexist.py'),
        ]
    
        for p in fail_plugins:
>           with pytest.raises(subprocess.CalledProcessError):
E           Failed: DID NOT RAISE <class 'subprocess.CalledProcessError'>

tests/test_plugin.py:420: Failed
----------------------------- Captured stdout call -----------------------------
{'github_repository': 'ElementsProject/lightning', 'github_sha': '83dca18c5e9610bfaac766f957387b9a1ec48f50', 'github_ref': 'refs/pull/7887/merge', 'github_ref_name': 'HEAD', 'github_run_id': 13253210143, 'github_head_ref': 'guilt/bolt-updates-after-24.11', 'github_run_number': 12237, 'github_base_ref': 'master', 'github_run_attempt': '2', 'testname': 'test_failing_plugins', 'start_time': 1739239278, 'end_time': 1739239340, 'outcome': 'fail'}
=========================== short test summary info ============================
FAILED tests/test_plugin.py::test_failing_plugins - Failed: DID NOT RAISE <class 'subprocess.CalledProcessError'>
============= 1 failed, 80 passed, 2 skipped in 855.37s (0:14:15) ==============
```
2025-02-11 08:40:29 -06:00
Rusty Russell
3b16637c27 pytest: fix race in test_autoclean
We can actually delete it before counters are updated:

```
        wait_for(lambda: len(l3.rpc.listinvoices()['invoices']) == 2)
>       assert l3.rpc.autoclean_status()['autoclean']['expiredinvoices']['cleaned'] == 3
E       assert 1 == 3

tests/test_plugin.py:3266: AssertionError
```

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2025-02-11 08:40:29 -06:00
Dusty Daemon
9c3941071a dev: startup_regtest using wrong null dir
Swiching to /dev/null instead of typo’d /tmp/null

Changelog-None
2025-02-11 12:58:27 +10:30
Rusty Russell
4e7ba96729 lightningd: don't kill onchaind if we are forcing a disconnect.
We thought it was a good idea to terminate channel subds, but we included onchaind as well!

```
2025-01-29T21:31:46.053Z UNUSUAL 03…00-channeld-chan#255683: Adding HTLC 1737 too slow: killing connection
2025-01-29T21:31:46.053Z INFO    03…00-chan#255683: Peer transient failure in CHANNELD_NORMAL: Adding HTLC timed out: killed connection
2025-01-29T21:31:46.053Z DEBUG   03…00-channeld-chan#255683: Status closed, but not exited. Killing
2025-01-29T21:31:46.054Z DEBUG   03…00-chan#255683: Failing HTLC 1738 due to peer death
2025-01-29T21:31:46.058Z DEBUG   03…00-chan#255683: Failing HTLC 1737 due to peer death
2025-01-29T21:31:46.058Z DEBUG   03…00-chan#255673: Forcing disconnect due to One channel had an error
2025-01-29T21:31:46.059Z DEBUG   03…00-onchaind-chan#255673: Status closed, but not exited. Killing
2025-01-29T21:31:46.093Z DEBUG   03…00-connectd: disconnect_peer
2025-01-29T21:31:46.093Z DEBUG   03…00-lightningd: peer_disconnect_done
```

Reported-by: @whitslack
Fixes: https://github.com/ElementsProject/lightning/issues/8055
Changelog-Fixed: onchaind: don't die if we fail an unrelated channel with the same peer.
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2025-02-10 19:19:12 -06:00
Rusty Russell
ee3133f198 lightningd: increase startup time for plugins to 120 seconds.
Raspberry Pi, with bitcoind running and full gossip topology may actually hit
this, and we have a report in practice.

Note that the comment is wrong, so fix that too.

Fixes: https://github.com/ElementsProject/lightning/issues/7724
Reported-by: m-schmoock
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2025-02-10 16:06:36 -06:00
ShahanaFarooqui
7a1b126d49 plugins: Delete old clnrest directory from plugins
Changelog-None.
2025-02-10 14:24:59 +10:30
ShahanaFarooqui
2448c80a8a doc: Updated REST documentation 2025-02-10 14:24:59 +10:30
ShahanaFarooqui
1776e469a7 clnrest: Rename cln-rest to rest-plugin as per current naming standards 2025-02-10 14:24:59 +10:30
ShahanaFarooqui
816970fdff pyln-testing: Removing the lightning- prefix check for schema files
Currently, pyln tests fail if the `lightning-` prefix is removed from schema/*.json files. In this release, we will update pyln to remove its reliance on this prefix, and in the next release, we will remove the prefixes from the files as well.

Changelog-None.
2025-02-07 15:41:22 -06:00
niftynei
fc08340d74 bkpr: fixup htlc penalty test with anchors
Test flake where the balance for lightning-2 went negative

```
>       assert account_balance(l2, channel_id) == 0

tests/test_closing.py:1314:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
tests/utils.py:183: in account_balance
    m_sum -= Millisatoshi(m['debit_msat'])
contrib/pyln-client/pyln/client/lightning.py:193: in __sub__
    return Millisatoshi(int(self) - int(other))
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = -10000msat, v = -10000
```

Led me to look into this test. lightning-2 should go negative since we
roll back the amounts it's received by going to a prior database state.

Rather than trying to do the right thing with obviously broken node
records, instead we just stop trying to account for them correctly
(impossible).

I also noticed that the anchor tests were failing the utxo output
matchup, which we should be asserting on it. The HTLC RBF that our
anchor code creates was causing an issue by creating another wallet
deposit utxo under the HTLC output. We now optionally add this utxo
in the case that anchors are turned on.

Changelog-None: Fix test flake
2025-02-07 14:38:54 -06:00
niftynei
473aefd9cb bkpr tests: return actual error data, not just a blank assert failure
It's really hard to tell what on earth went wrong when a coin movement
check fails, since we dont' return good error info.

Here we replace almost every `assert` with a proper check + error with
message to help make debugging easier.

cc @rustyrussell

Changelog-None: improve failure messages
2025-02-07 14:38:54 -06:00
Dusty Daemon
755c807477 splice: Test for missing user signatures 2025-02-07 12:49:20 -06:00
Dusty Daemon
5818b522f5 splice: Don’t let users do unsigned splices
If a user tries to do a splice without signing their inputs we now provide them with a nice error message and cancel the RPC since that wouldn’t be productive for the user anyway.

We also add a helpful message if they do the opposite — try to sign a PSBT where they did not add any inputs.

Changelog-Changed: Update prevents users from trying to splice unsigned PSBTs — protecting against potential issues.
2025-02-07 12:49:20 -06:00
Lagrang3
3f2b49022e xpay-handle-pay: test null params
Changelog-None: xpay-handle-pay: test null params in json array.

Signed-off-by: Lagrang3 <lagrang3@protonmail.com>
2025-02-06 12:46:38 -06:00
Lagrang3
21195be3f7 xpay-handle-pay: don't assume bolt11 is non NULL
Changelog-None: xpay-handle-pay: don't assume bolt11 param is non NULL

Signed-off-by: Lagrang3 <lagrang3@protonmail.com>
2025-02-06 12:46:38 -06:00
Lagrang3
a272258fb6 xpay-handle-pay: bugfix, handle null parameters
Changelog-Fixed: xpay-handle-pay: handle null parameters passed in the "param" list.

Reported-by: @hMsats
Signed-off-by: Lagrang3 <lagrang3@protonmail.com>
2025-02-06 12:46:38 -06:00
Rusty Russell
b78b3232e3 lightningd: implement unblacklist.
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
Changelog-Added: JSON-RPC: `blacklistrune` now has an option to un-blacklist (`relist`).
2025-02-05 16:43:09 -06:00
Rusty Russell
d72f045db9 lightningd: represent runes blacklist as simple bitmap.
Sure, we have to convert to and from the db set-of-pairs, but that's far simpler
than dealing with the current structure now we want to add code to *remove* from
the blacklist.

Changelog-Changed: JSON-RPC: `blacklistrune` no longer supports of runes over id 100,000,000.
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2025-02-05 16:43:09 -06:00
Rusty Russell
7b1e36d922 wallet: remove migration code for old commando runes.
This migration was introduced in dccbccf8f2 (pre 23.08), so the only way they
would need this is if they migration straight from 23.05 to 25.02.  And then
the solution is to migration to a prior one first, but I'll bet good money
we never, ever see this message:

   Commando runes still present?  Migration removed in v25.02: call Rusty!

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2025-02-05 16:43:09 -06:00
Dusty Daemon
8151c037bb Splice: Stricter interop errors
Error when our peer tries to use the shared output txid as well as the prevtx bytes.

Changelog-Changed: Stricter tests for interop with Eclair
2025-02-05 12:50:24 -06:00
Dusty Daemon
a22fe31904 Splice: Fix comment typo 2025-02-05 12:50:24 -06:00
Dusty Daemon
9e29bde9a6 Add ‘v’ to the version from zipfile release
When building from a release zipfile and there is no `git` present, the version number lacks a ‘v’.

This triggers db.c to fail it’s `is_released_version` check, which fails because the version not start with a ‘v’ — thereby the database upgrade is rejected.

Issue reported by TonyV on Discord:
“Hey guys, I just upgraded to the latest release and am now getting
```
Refusing to irreversibly upgrade db from version 219 to 261 in non-final version 24.11.1 (use --database-upgrade=true to override)
```
I have the db backed up... but am I good to make those changes without breaking my channels?”

Changelog-Changed: Fix for people upgrading using source release zip packages.
2025-02-04 16:44:18 -06:00
Rusty Russell
fc9f062124 gossipd: extra debugging when inject fails.
test_closing_different_fees fails:

```
2024-10-14T08:43:30.2733614Z
2024-10-14T08:43:30.2734133Z         # Now wait for them all to hit normal state, do payments
2024-10-14T08:43:30.2735205Z >       l1.daemon.wait_for_logs(['update for channel .* now ACTIVE'] * num_peers
2024-10-14T08:43:30.2736233Z                                 + ['to CHANNELD_NORMAL'] * num_peers)
2024-10-14T08:43:30.2736725Z
2024-10-14T08:43:30.2736903Z tests/test_closing.py:230:
...
2024-10-14T08:43:30.2761325Z E                   TimeoutError: Unable to find "[re.compile('update for channel .* now ACTIVE')]" in logs.
```

For some reason one of the channel_update injections does *not* evoke this message
from gossipd...

Changelog-None: debug!
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2025-02-04 13:18:00 -06:00
ShahanaFarooqui
54555ce5e7 doc: Add new createrune example
- Moved the `Usage` section further down in `createrune` and `commando-rune` for improved UX.
- Added a new example for creating a rune with `read-only` restrictions, extending it to allow only payments of `less than 100,000 sats per day` using the `pay` or `xpay` methods.
- Adjusted formatting by appending an extra space after the `dependentUpon` condition, fixing `[*start* [*end*]][*relist*]` to `[*start* [*end*]] [*relist*]`.
- Relocated `Examples` from the expandable section to a standard heading, as examples are now already placed at the end of the page.

Changelog-None.
2025-02-04 20:12:59 +10:30
ShahanaFarooqui
0db282a069 ci: Update Rust version on Dockerfiles for Ubuntu
After merging the Rust-based `clnrest` plugin into the master, all three reproducible build scripts failed with the following error:

```
error: package `socketioxide v0.15.1` cannot be built because it requires rustc 1.75.0 or newer, while the currently active rustc version is 1.73.0
Either upgrade to rustc 1.75.0 or newer, or use
cargo update -p socketioxide@0.15.1 --precise ver
where `ver` is the latest version of `socketioxide` supporting rustc 1.73.0
make: *** [plugins/Makefile:304: target/release/clnrest] Error 101
```

To resolve this, we can either downgrade `socketioxide` to `v0.11.1`, which is compatible with `Rust >=v1.67` OR Upgrade Rust to `v1.75`.

Since the latest Rust version is `1.84`, upgrading to `1.75` seems like a reasonable choice, as it is already 13 months old.

Changelog-None.
2025-01-31 07:17:59 +10:30
niftynei
cac7022c7a startup-regtest: only inspect current run's logs for clnrest updates
If you re-run a node several times, the log file fills with info from
previous runs. To avoid looking at old logs, only parse the most recent
run's logs when looking for the magic CLN rest startup/deactivated
strings

Changelog-Fixed: startup-regtest.sh now only inspects the most recent run's logs for the active status of the clnrest plugin
2025-01-29 18:32:23 -08:00
niftynei
43905dfb0e startup-regtest: look for clnrest binary on startup
Just check for the presence of the clnrest binary now.

Also update the string to check to the actual REST startup string
2025-01-29 18:32:23 -08:00
daywalker90
cac9315c00 clnrest: replace with rust plugin
Changelog-Changed: clnrest is now a rust plugin
2025-01-29 18:32:23 -08:00
Christian Decker
94e70b8124 pay: Print the HTLC result as soon as it's known
We used to not print what happened with an HTLC in the `pay`
plugin. This meant that to follow the HTLCs we'd have to map the `pay`
HTLCs to the `lightningd` HTLCs, and then trace that. BY having `pay`
print the outcome as it sees it, we can make that tracking much
simpler, even allowing for tooling to do it for us.

Changelog-None This is a log-only change
2025-01-30 09:35:50 +10:30
ShahanaFarooqui
9df9441aa3 ci: Move the 'update doc examples' script to a later stage in the CI pipeline
Changelog-None.
2025-01-30 09:34:59 +10:30
ShahanaFarooqui
7f73d312e8 ci: Fix for reproducible noble build failure
Changelog-None.
2025-01-30 09:34:01 +10:30
ShahanaFarooqui
d4899ea6fe doc: Add editdescriptionbyoutpoint and editdescriptionbypaymentid in documentation
Adding the newly introduced RPCs, `editdescriptionbyoutpoint` and `editdescriptionbypaymentid`, to the `Makefile` for generating the corresponding `.md` files required for the documentation portal.

Changelog-None.
2025-01-28 18:24:46 +10:30
ShahanaFarooqui
b1fbbb0405 ci: Version update for Fedora reproducible build
Closes #7902.

Changelog-None.
2025-01-28 14:50:45 +10:30
ShahanaFarooqui
1bf92c2dad docs: Remove lightning- prefix from all RPCs
Changelog-None.
2025-01-28 10:55:38 +10:30
Rusty Russell
e0aaf60bbd askrene: don't crash, just report, when a flow's remaining capacity is negative.
I'm not sure why this happens, and suspect it is caused by an issue elsewhere, so
add some verbose debugging, don't crash.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
Fixes: https://github.com/ElementsProject/lightning/issues/8017
2025-01-28 10:53:22 +10:30
Rusty Russell
c31eed433c askrene: expose fmt_flow_full and make more generic.
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2025-01-28 10:53:22 +10:30
Rusty Russell
3387bba9be askrene: don't create 0-msat flow in corner case.
Shouldn't happen, but I can't *prove* it's impossible.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2025-01-28 10:53:22 +10:30
Rusty Russell
43130a33be xpay: make sure we report if we ever try to call getroutes with 0msat.
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2025-01-28 10:53:22 +10:30
Rusty Russell
89ca5aef9f common: don't crash on send_backtrace() if bt_print is NULL.
This (and bt_exit) are NULL for libplugin.  We don't always want to crash!

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2025-01-28 10:53:22 +10:30
Rusty Russell
fd7ac4e05b xpay: refuse request to pay 0msat.
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
Changelog-Fixed: JSON-RPC: `xpay` will refuse to make a 0msat payment (0msat invoice, partial payment, or manually-set on amountless invoice).
Fixes: https://github.com/ElementsProject/lightning/issues/8016
2025-01-28 10:53:22 +10:30
Rusty Russell
01bce4e7b7 askrene: don't crash if asked to route 0 msat.
But don't allow it either.

```
Jan 19 13:18:52 boltz lightningd[2259911]: cln-askrene: plugins/askrene/algorithm.c:274: simple_feasibleflow: Assertion `amount > 0' failed.
Jan 19 13:18:52 boltz lightningd[2259911]: cln-askrene: FATAL SIGNAL 6 (version v24.11.1-1-ge9dbdeb)
Jan 19 13:18:52 boltz lightningd[2259911]: 0x5576e212b407 send_backtrace
Jan 19 13:18:52 boltz lightningd[2259911]:         common/daemon.c:33
Jan 19 13:18:52 boltz lightningd[2259911]: 0x5576e212b49e crashdump
Jan 19 13:18:52 boltz lightningd[2259911]:         common/daemon.c:75
Jan 19 13:18:52 boltz lightningd[2259911]: 0x7f964ba9251f ???
Jan 19 13:18:52 boltz lightningd[2259911]:         ???:0
Jan 19 13:18:52 boltz lightningd[2259911]: 0x7f964bae69fc ???
Jan 19 13:18:52 boltz lightningd[2259911]:         ???:0
Jan 19 13:18:52 boltz lightningd[2259911]: 0x7f964ba92475 ???
Jan 19 13:18:52 boltz lightningd[2259911]:         ???:0
Jan 19 13:18:52 boltz lightningd[2259911]: 0x7f964ba787f2 ???
Jan 19 13:18:52 boltz lightningd[2259911]:         ???:0
Jan 19 13:18:52 boltz lightningd[2259911]: 0x7f964ba7871a ???
Jan 19 13:18:52 boltz lightningd[2259911]:         ???:0
Jan 19 13:18:52 boltz lightningd[2259911]: 0x7f964ba89e95 ???
Jan 19 13:18:52 boltz lightningd[2259911]:         ???:0
Jan 19 13:18:52 boltz lightningd[2259911]: 0x5576e211695e simple_feasibleflow
Jan 19 13:18:52 boltz lightningd[2259911]:         plugins/askrene/algorithm.c:274
Jan 19 13:18:52 boltz lightningd[2259911]: 0x5576e2111495 minflow
Jan 19 13:18:52 boltz lightningd[2259911]:         plugins/askrene/mcf.c:1014
Jan 19 13:18:52 boltz lightningd[2259911]: 0x5576e210bc74 get_routes
Jan 19 13:18:52 boltz lightningd[2259911]:         plugins/askrene/askrene.c:414
Jan 19 13:18:52 boltz lightningd[2259911]: 0x5576e210c610 do_getroutes
Jan 19 13:18:52 boltz lightningd[2259911]:         plugins/askrene/askrene.c:615
Jan 19 13:18:52 boltz lightningd[2259911]: 0x5576e210cad8 listpeerchannels_done
Jan 19 13:18:52 boltz lightningd[2259911]:         plugins/askrene/askrene.c:741
Jan 19 13:18:52 boltz lightningd[2259911]: 0x5576e211b35a handle_rpc_reply
Jan 19 13:18:52 boltz lightningd[2259911]:         plugins/libplugin.c:1084
Jan 19 13:18:52 boltz lightningd[2259911]: 0x5576e211b54c rpc_read_response_one
Jan 19 13:18:52 boltz lightningd[2259911]:         plugins/libplugin.c:1388
Jan 19 13:18:52 boltz lightningd[2259911]: 0x5576e211b5fd rpc_conn_read_response
Jan 19 13:18:52 boltz lightningd[2259911]:         plugins/libplugin.c:1412
Jan 19 13:18:52 boltz lightningd[2259911]: 0x5576e214fe8f next_plan
Jan 19 13:18:52 boltz lightningd[2259911]:         ccan/ccan/io/io.c:60
Jan 19 13:18:52 boltz lightningd[2259911]: 0x5576e215036e do_plan
Jan 19 13:18:52 boltz lightningd[2259911]:         ccan/ccan/io/io.c:422
Jan 19 13:18:52 boltz lightningd[2259911]: 0x5576e215042b io_ready
Jan 19 13:18:52 boltz lightningd[2259911]:         ccan/ccan/io/io.c:439
Jan 19 13:18:52 boltz lightningd[2259911]: 0x5576e2151e2e io_loop
Jan 19 13:18:52 boltz lightningd[2259911]:         ccan/ccan/io/poll.c:455
Jan 19 13:18:52 boltz lightningd[2259911]: 0x5576e211cc29 plugin_main
Jan 19 13:18:52 boltz lightningd[2259911]:         plugins/libplugin.c:2488
Jan 19 13:18:52 boltz lightningd[2259911]: 0x5576e210cb38 main
Jan 19 13:18:52 boltz lightningd[2259911]:         plugins/askrene/askrene.c:1262
Jan 19 13:18:52 boltz lightningd[2259911]: 0x7f964ba79d8f ???
```

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
Changelog-Fixed: JSON-RPC: `getroutes` will refuse, not crash, if asked to find a route fr 0msat.
2025-01-28 10:53:22 +10:30
Rusty Russell
4e887c7c67 lightningd: add option to crash itself after some time.
We have CI runs which timeout (after 2 hours).  It's not clear why,
but we can at least eliminate CLN lockups as the answer.

Since pytest disabled the --timeout option on test shutdown, we could be
seeing an issue on stopping taking a long time?

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2025-01-27 11:07:04 +10:30
Rusty Russell
9565b3a4a3 pytest: fix flake in test_onchain_slow_anchor.
If we get "lucky" then commit tx will have short sig, one less weight (1 in 256 chance):

```
    @unittest.skipIf(TEST_NETWORK != 'regtest', 'elementsd anchors not supportd')
    def test_onchain_slow_anchor(node_factory, bitcoind):
        """We still use anchors for non-critical closes"""
        l1, l2 = node_factory.line_graph(2)
    
        # Don't let l1 succeed in sending commit tx
        def censoring_sendrawtx(r):
            return {'id': r['id'], 'result': {}}
    
        l1.daemon.rpcproxy.mock_rpc('sendrawtransaction', censoring_sendrawtx)
    
        close_start_depth = bitcoind.rpc.getblockchaininfo()['blocks']
    
        # Make l1 close unilaterally.
        l1.rpc.disconnect(l2.info['id'], force=True)
        l1.rpc.close(l2.info['id'], unilateraltimeout=1)
    
        # We will have a super-low-prio anchor spend.
        l1.daemon.wait_for_log(r"Low-priority anchorspend aiming for block {} \(feerate 253\)".format(close_start_depth + 2016))
    
        # Restart with reduced block time.
        l1.stop()
        l1.daemon.opts['dev-low-prio-anchor-blocks'] = 20
        l1.start()
    
        l1.daemon.wait_for_log("Low-priority anchorspend aiming for block {}".format(close_start_depth + 20))
        l1.daemon.wait_for_log("Anchorspend for local commit tx")
    
        # Won't go under 12 blocks though.
    
        # Make sure it sees all these blocks at once, to avoid test flakes!
        l1.stop()
        bitcoind.generate_block(7)
        l1.start()
    
        height = bitcoind.rpc.getblockchaininfo()['blocks']
        l1.daemon.wait_for_log(r"Low-priority anchorspend aiming for block {} \(feerate 7458\)".format(height + 13))
>       l1.daemon.wait_for_log(r"Anchorspend for local commit tx fee 12335sat \(w=714\), commit_tx fee 4545sat \(w=768\): package feerate 11390 perkw")
```

Here's the log we *did* get:

```
2025-01-25T08:46:40.9399213Z lightningd-1 2025-01-25T08:40:06.312Z DEBUG   022d223620a359a47ff7f7ac447c85c46c923da53389221a0054c11c1e3ca31d59-chan#1: Anchorspend for local commit tx fee 12328sat (w=714), commit_tx fee 4545sat (w=767): package feerate 11392 perkw
```

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2025-01-27 11:07:04 +10:30
Rusty Russell
e1e476fd39 pytest: mark test_rbf_reconnect_tx_construct flaky:
Doesn't always die messily, it seems?


```
    @unittest.skipIf(TEST_NETWORK != 'regtest', 'elementsd doesnt yet support PSBT features we need')
    @pytest.mark.openchannel('v2')
    def test_rbf_reconnect_tx_construct(node_factory, bitcoind, chainparams):
        disconnects = ['=WIRE_TX_ADD_INPUT',  # Initial funding succeeds
                       '-WIRE_TX_ADD_INPUT',
                       '+WIRE_TX_ADD_INPUT',
                       '-WIRE_TX_ADD_OUTPUT',
                       '+WIRE_TX_ADD_OUTPUT',
                       '-WIRE_TX_COMPLETE',
                       '+WIRE_TX_COMPLETE',
                       '-WIRE_COMMITMENT_SIGNED',
                       '+WIRE_COMMITMENT_SIGNED']
    
        l1, l2 = node_factory.get_nodes(2,
                                        opts=[{'disconnect': disconnects,
                                               'may_reconnect': True,
                                               'dev-no-reconnect': None},
                                              {'may_reconnect': True,
                                               'dev-no-reconnect': None,
                                               'broken_log': 'dualopend daemon died before signed PSBT returned'}])
    
        l1.rpc.connect(l2.info['id'], 'localhost', l2.port)
        amount = 2**24
        chan_amount = 100000
        bitcoind.rpc.sendtoaddress(l1.rpc.newaddr()['bech32'], amount / 10**8 + 0.01)
        bitcoind.generate_block(1)
        # Wait for it to arrive.
        wait_for(lambda: len(l1.rpc.listfunds()['outputs']) > 0)
    
        res = l1.rpc.fundchannel(l2.info['id'], chan_amount)
        chan_id = res['channel_id']
        vins = bitcoind.rpc.decoderawtransaction(res['tx'])['vin']
        assert(only_one(vins))
        prev_utxos = ["{}:{}".format(vins[0]['txid'], vins[0]['vout'])]
    
        # Check that we're waiting for lockin
        l1.daemon.wait_for_log(' to DUALOPEND_AWAITING_LOCKIN')
    
        # rbf the lease with a higher amount
        rate = int(find_next_feerate(l1, l2)[:-5])
        # We 4x the feerate to beat the min-relay fee
        next_feerate = '{}perkw'.format(rate * 4)
    
        # Initiate an RBF
        startweight = 42 + 172  # base weight, funding output
        initpsbt = l1.rpc.utxopsbt(chan_amount, next_feerate, startweight,
                                   prev_utxos, reservedok=True,
                                   excess_as_change=True)
    
        # Run through TX_ADD wires
        for d in disconnects[1:-4]:
            l1.rpc.connect(l2.info['id'], 'localhost', l2.port)
            with pytest.raises(RpcError):
                l1.rpc.openchannel_bump(chan_id, chan_amount, initpsbt['psbt'])
            wait_for(lambda: l1.rpc.getpeer(l2.info['id'])['connected'] is False)
    
        # The first TX_COMPLETE breaks
        l1.rpc.connect(l2.info['id'], 'localhost', l2.port)
        bump = l1.rpc.openchannel_bump(chan_id, chan_amount, initpsbt['psbt'])
        with pytest.raises(RpcError):
            update = l1.rpc.openchannel_update(chan_id, bump['psbt'])
        wait_for(lambda: l1.rpc.getpeer(l2.info['id'])['connected'] is False)
        l1.rpc.connect(l2.info['id'], 'localhost', l2.port)
        # l1 should remember, l2 has forgotten
        # l2 should send tx-abort, to reset
        l2.daemon.wait_for_log(r'tx-abort: Sent next_funding_txid .* doesn\'t match ours .*')
        l1.daemon.wait_for_log(r'Cleaned up incomplete inflight')
        # abort doesn't cause a disconnect
        assert l1.rpc.getpeer(l2.info['id'])['connected']
    
        # The next TX_COMPLETE break (both remember) + they break on the
        # COMMITMENT_SIGNED during the reconnect
        bump = l1.rpc.openchannel_bump(chan_id, chan_amount, initpsbt['psbt'])
        with pytest.raises(RpcError):
            update = l1.rpc.openchannel_update(chan_id, bump['psbt'])
        wait_for(lambda: l1.rpc.getpeer(l2.info['id'])['connected'] is False)
        l1.rpc.connect(l2.info['id'], 'localhost', l2.port)
        l2.daemon.wait_for_logs([r'Got dualopend reestablish',
                                 r'No commitment, not sending our sigs'])
        l1.daemon.wait_for_logs([r'Got dualopend reestablish',
                                 r'No commitment, not sending our sigs',
                                 r'dev_disconnect: -WIRE_COMMITMENT_SIGNED',
                                 'peer_disconnect_done'])
        assert not l1.rpc.getpeer(l2.info['id'])['connected']
        l1.rpc.connect(l2.info['id'], 'localhost', l2.port)
    
        # COMMITMENT_SIGNED disconnects *during* the reconnect
        # We can't bump because the last negotiation is in the wrong state
        with pytest.raises(RpcError, match=r'Funding sigs for this channel not secured'):
            l1.rpc.openchannel_bump(chan_id, chan_amount, initpsbt['psbt'])
        # l2 reconnects, but doesn't have l1's commitment
>       l2.daemon.wait_for_logs([r'Got dualopend reestablish',
                                 r'No commitment, not sending our sigs',
                                 # This is a BROKEN log, it's expected!
                                 r'dualopend daemon died before signed PSBT returned'])

tests/test_opening.py:944: 
...
>                   raise TimeoutError('Unable to find "{}" in logs.'.format(exs))
E                   TimeoutError: Unable to find "[re.compile('dualopend daemon died before signed PSBT returned')]" in logs.
```

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2025-01-27 11:07:04 +10:30
Rusty Russell
21cd11825a pytest: fix flake in test_onchain_reestablish_reply
We can ask for the state too fast, before WIRE_ERROR is processed:

```
2025-01-24T14:17:57.4799255Z ________________________ test_onchain_reestablish_reply ________________________
2025-01-24T14:17:57.4800383Z [gw2] linux -- Python 3.10.16 /home/runner/.cache/pypoetry/virtualenvs/cln-meta-project-AqJ9wMix-py3.10/bin/python
2025-01-24T14:17:57.4801246Z 
2025-01-24T14:17:57.4802068Z node_factory = <pyln.testing.utils.NodeFactory object at 0x7f66ec144400>
2025-01-24T14:17:57.4802645Z bitcoind = <pyln.testing.utils.BitcoinD object at 0x7f66ec145ab0>
2025-01-24T14:17:57.4803483Z executor = <concurrent.futures.thread.ThreadPoolExecutor object at 0x7f66ec146da0>
2025-01-24T14:17:57.4804029Z 
2025-01-24T14:17:57.4804340Z     def test_onchain_reestablish_reply(node_factory, bitcoind, executor):
2025-01-24T14:17:57.4805013Z         l1, l2, l3 = node_factory.line_graph(3, opts={'may_reconnect': True,
2025-01-24T14:17:57.4805572Z                                                       'dev-no-reconnect': None})
2025-01-24T14:17:57.4805990Z     
2025-01-24T14:17:57.4806262Z         # Make l1 close unilaterally.
2025-01-24T14:17:57.4806697Z         l1.rpc.disconnect(l2.info['id'], force=True)
2025-01-24T14:17:57.4807200Z         l1.rpc.close(l2.info['id'], unilateraltimeout=1)
2025-01-24T14:17:57.4807622Z     
2025-01-24T14:17:57.4808025Z         # l2 doesn't know, reconnection should get REESTABLISH *then* error.
2025-01-24T14:17:57.4808637Z         l2.rpc.connect(l1.info['id'], 'localhost', l1.port)
2025-01-24T14:17:57.4809066Z     
2025-01-24T14:17:57.4809334Z         # We should exchange messages
2025-01-24T14:17:57.4809835Z         l2.daemon.wait_for_logs(["peer_out WIRE_CHANNEL_REESTABLISH",
2025-01-24T14:17:57.4810399Z                                  "peer_in WIRE_CHANNEL_REESTABLISH"])
2025-01-24T14:17:57.4811197Z         # It should be OK
2025-01-24T14:17:57.4811642Z         l2.daemon.wait_for_log("Reconnected, and reestablished.")
2025-01-24T14:17:57.4812116Z     
2025-01-24T14:17:57.4812378Z         # Then we get the error, close.
2025-01-24T14:17:57.4812824Z         l2.daemon.wait_for_log("peer_in WIRE_ERROR")
2025-01-24T14:17:57.4813576Z >       assert only_one(l2.rpc.listpeerchannels(l1.info['id'])['channels'])['state'] == 'AWAITING_UNILATERAL'
2025-01-24T14:17:57.4814446Z E       AssertionError: assert 'CHANNELD_NORMAL' == 'AWAITING_UNILATERAL'
2025-01-24T14:17:57.4815014Z E         - AWAITING_UNILATERAL
2025-01-24T14:17:57.4815362Z E         + CHANNELD_NORMAL
```

```
2025-01-24T14:17:57.5760435Z lightningd-2 2025-01-24T14:04:28.398Z DEBUG   0266e4598d1d3c415f572a8488830b60f7e744ed9235eb0b1ba93283b315c03518-channeld-chan#1: peer_in WIRE_ERROR
2025-01-24T14:17:57.5760674Z lightningd-2 2025-01-24T14:04:28.401Z TRACE   lightningd: Calling rpc_command hook of plugin cln-xpay
2025-01-24T14:17:57.5760935Z lightningd-2 2025-01-24T14:04:28.403Z TRACE   lightningd: Plugin cln-xpay returned from rpc_command hook call
2025-01-24T14:17:57.5761176Z lightningd-2 2025-01-24T14:04:28.408Z TRACE   lightningd: Calling rpc_command hook of plugin cln-xpay
2025-01-24T14:17:57.5761430Z lightningd-2 2025-01-24T14:04:28.414Z TRACE   lightningd: Plugin cln-xpay returned from rpc_command hook call
2025-01-24T14:17:57.5762598Z {'github_repository': 'ElementsProject/lightning', 'github_sha': '390503b31e1949cb84e5a5257bf29a1b80d5cd20', 'github_ref': 'refs/pull/8027/merge', 'github_ref_name': 'HEAD', 'github_run_id': 12950414032, 'github_head_ref': 'guilt/fix-flakes12', 'github_run_number': 12051, 'github_base_ref': 'master', 'github_run_attempt': '1', 'testname': 'test_onchain_reestablish_reply', 'start_time': 1737727408, 'end_time': 1737727468, 'outcome': 'fail'}
2025-01-24T14:17:57.5763430Z lightningd-2 2025-01-24T14:04:28.426Z DEBUG   0266e4598d1d3c415f572a8488830b60f7e744ed9235eb0b1ba93283b315c03518-channeld-chan#1: billboard perm: Received ERROR channel 69d744488de7ec7f4c018da98a8a9d726ee3b47a97809608e4ce6f17747b5f09: Forcibly closed by `close` command timeout
2025-01-24T14:17:57.5764512Z lightningd-2 2025-01-24T14:04:28.433Z UNUSUAL 0266e4598d1d3c415f572a8488830b60f7e744ed9235eb0b1ba93283b315c03518-chan#1: Peer permanent failure in CHANNELD_NORMAL: channeld: received ERROR channel 69d744488de7ec7f4c018da98a8a9d726ee3b47a97809608e4ce6f17747b5f09: Forcibly closed by `close` command timeout (reason=protocol)
2025-01-24T14:17:57.5764997Z lightningd-2 2025-01-24T14:04:28.439Z INFO    0266e4598d1d3c415f572a8488830b60f7e744ed9235eb0b1ba93283b315c03518-chan#1: State changed from CHANNELD_NORMAL to AWAITING_UNILATERAL
```

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2025-01-27 11:07:04 +10:30
Rusty Russell
f68700908e pytest: make test_gossip_throttle more reliable.
By having gossipwith filter out messages we don't want, we can get the counts of
expected messages correct, and not hit errors like this:

```
    def test_gossip_throttle(node_factory, bitcoind, chainparams):
        """Make some gossip, test it gets throttled"""
        l1, l2, l3, l4 = node_factory.line_graph(4, wait_for_announce=True,
                                                 opts=[{}, {}, {}, {'dev-throttle-gossip': None}])
    
        # We expect: self-advertizement (3 messages for l1 and l4) plus
        # 4 node announcements, 3 channel announcements and 6 channel updates.
        # We also expect it to send a timestamp filter message.
        # (We won't take long enough to get a ping!)
        expected = 4 + 4 + 3 + 6 + 1
    
        # l1 is unlimited
        start_fast = time.time()
        out1 = subprocess.run(['devtools/gossipwith',
                               '--all-gossip',
                               '--hex',
                               '--network={}'.format(TEST_NETWORK),
                               '--max-messages={}'.format(expected),
                               '{}@localhost:{}'.format(l1.info['id'], l1.port)],
                              check=True,
                              timeout=TIMEOUT, stdout=subprocess.PIPE).stdout.split()
        time_fast = time.time() - start_fast
        assert time_fast < 2
        # Remove timestamp filter, since timestamp will change!
        out1 = [m for m in out1 if not m.startswith(b'0109')]
    
        # l4 is throttled
        start_slow = time.time()
        out2 = subprocess.run(['devtools/gossipwith',
                               '--all-gossip',
                               '--hex',
                               '--network={}'.format(TEST_NETWORK),
                               '--max-messages={}'.format(expected),
                               '{}@localhost:{}'.format(l4.info['id'], l4.port)],
                              check=True,
                              timeout=TIMEOUT, stdout=subprocess.PIPE).stdout.split()
        time_slow = time.time() - start_slow
        assert time_slow > 3
    
        # Remove timestamp filter, since timestamp will change!
        out2 = [m for m in out2 if not m.startswith(b'0109')]
    
        # Contents should be identical (once uniquified, since each
        # doubles-up on its own gossip)
>       assert set(out1) == set(out2)
E       AssertionError: assert {b'010054b1907bdf639c9060e0fa4bca02419c46f75a99f0908b87a2e09711d5d031ba76b8fd07acc8be1b2fac9e31efb808e5d362c32ef4665...
E         Extra items in the left set:
E         b'01010ad5be8b9ba029245c2ae2d667af7ead7c0129c479c7fd7145a9b65931e90222082e6e4ab37ef60ebd10f1493d73e8bf7a40c4ae5f7d87cc...8488830b60f7e744ed9235eb0b1ba93283b315c035180266e44a554e494f524245414d2d333930353033622d6d6f64646564000000000000000000'
E         Extra items in the right set:
E         b'01079f87eb580b9e5f11dc211e9fb66abb3699999044f8fe146801162393364286c6000000010000006c010101'
```

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2025-01-27 11:07:04 +10:30
Rusty Russell
f7714613bd devtools/gossipwith: filter for max-messages.
So not every message type counts: this is useful when we want to get a specific number
of a specific type.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2025-01-27 11:07:04 +10:30
Rusty Russell
cc2be867dc gossipd: don't prune if we haven't seen on side's update at all.
This caused a "flake" in testing, because it's wrong:

```
_____________________________ test_gossip_pruning ______________________________
[gw2] linux -- Python 3.10.16 /home/runner/.cache/pypoetry/virtualenvs/cln-meta-project-AqJ9wMix-py3.10/bin/python

node_factory = <pyln.testing.utils.NodeFactory object at 0x7f0267530490>
bitcoind = <pyln.testing.utils.BitcoinD object at 0x7f0267532b30>

    def test_gossip_pruning(node_factory, bitcoind):
        """ Create channel and see it being updated in time before pruning
        """
        l1, l2, l3 = node_factory.get_nodes(3, opts={'dev-fast-gossip-prune': None,
                                                     'allow_bad_gossip': True,
                                                     'autoconnect-seeker-peers': 0})
    
        l1.rpc.connect(l2.info['id'], 'localhost', l2.port)
        l2.rpc.connect(l3.info['id'], 'localhost', l3.port)
    
        scid1, _ = l1.fundchannel(l2, 10**6)
        scid2, _ = l2.fundchannel(l3, 10**6)
    
        mine_funding_to_announce(bitcoind, [l1, l2, l3])
        wait_for(lambda: l1.rpc.listchannels(source=l1.info['id'])['channels'] != [])
        l1_initial_cupdate_timestamp = only_one(l1.rpc.listchannels(source=l1.info['id'])['channels'])['last_update']
    
        # Get timestamps of initial updates, so we can ensure they change.
        # Channels should be activated locally
>       wait_for(lambda: [c['active'] for c in l1.rpc.listchannels()['channels']] == [True] * 4)
```

Here you can see it has pruned:

```
lightningd-1 2025-01-24T07:39:40.873Z DEBUG   gossipd: Pruning channel 105x1x0 from network view (ages 1737704380 and 0)
...
lightningd-1 2025-01-24T07:39:50.941Z UNUSUAL lightningd: Bad gossip order: could not find channel 105x1x0 for peer's channel update
```

Changelog-Fixed: Protocol: we were overzealous in pruning channels if we hadn't seen one side's gossip update yet.
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2025-01-27 11:07:04 +10:30
Rusty Russell
123f8ba9d6 pytest: fix race in test_reconnect_remote_sends_no_sigs
We can be a bit early in our assertion:

```
    @unittest.skipIf(os.getenv('TEST_DB_PROVIDER', 'sqlite3') != 'sqlite3', "sqlite3-specific DB manip")
    def test_reconnect_remote_sends_no_sigs(node_factory):
        """We re-announce, even when remote node doesn't send its announcement_signatures on reconnect.
        """
        l1, l2 = node_factory.line_graph(2, wait_for_announce=True, opts={'may_reconnect': True,
                                                                          'dev-no-reconnect': None})
    
        # Wipe l2's gossip_store
        l2.stop()
        gs_path = os.path.join(l2.daemon.lightning_dir, TEST_NETWORK, 'gossip_store')
        os.unlink(gs_path)
        l2.start()
    
        # l2 will now uses (REMOTE's) announcement_signatures it has stored
        wait_for(lambda: l2.rpc.listchannels()['channels'] != [])
    
        # Remove remote signatures from l1 so it asks for them (and delete gossip store)
        l1.db_manip("UPDATE channels SET remote_ann_node_sig=NULL, remote_ann_bitcoin_sig=NULL")
        gs_path = os.path.join(l1.daemon.lightning_dir, TEST_NETWORK, 'gossip_store')
        os.unlink(gs_path)
        l1.restart()
    
        l1.connect(l2)
        l1needle = l1.daemon.logsearch_start
        l2needle = l2.daemon.logsearch_start
    
        # l1 asks once, l2 replies once.
        # Make sure we get all the msgs!
        time.sleep(5)
    
        l1.daemon.wait_for_log('peer_out WIRE_ANNOUNCEMENT_SIGNATURES')
        l2.daemon.wait_for_log('peer_out WIRE_ANNOUNCEMENT_SIGNATURES')
    
        l1msgs = [l.split()[4] for l in l1.daemon.logs[l1needle:] if 'WIRE_ANNOUNCEMENT_SIGNATURES' in l]
>       assert l1msgs == ['peer_out', 'peer_in']
E       AssertionError: assert ['peer_out'] == ['peer_out', 'peer_in']
E         Right contains one more item: 'peer_in'
E         Full diff:
E         - ['peer_out', 'peer_in']
E         + ['peer_out']
```

```
lightningd-2 2025-01-24T05:53:22.862Z DEBUG   0266e4598d1d3c415f572a8488830b60f7e744ed9235eb0b1ba93283b315c03518-connectd: peer_out WIRE_ANNOUNCEMENT_SIGNATURES
lightningd-1 2025-01-24T05:53:22.864Z DEBUG   022d223620a359a47ff7f7ac447c85c46c923da53389221a0054c11c1e3ca31d59-channeld-chan#1: peer_in WIRE_ANNOUNCEMENT_SIGNATURES
lightningd-1 2025-01-24T05:53:22.885Z DEBUG   022d223620a359a47ff7f7ac447c85c46c923da53389221a0054c11c1e3ca31d59-chan#1: channel_gossip: received announcement sigs for 103x1x0 (we have 103x1x0)
{'github_repository': 'ElementsProject/lightning', 'github_sha': 'e9d36f2b8ecd45882753cbe062c355e40bc7109c', 'github_ref': 'refs/pull/8027/merge', 'github_ref_name': 'HEAD', 'github_run_id': 12943530601, 'github_head_ref':
```

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2025-01-27 11:07:04 +10:30
Rusty Russell
7ab1037646 pytest: fix flake in test_connect_ratelimit.
Sometimes they connect too fast, so we don't get a chance to ratelimit all of them:

```
    def test_connect_ratelimit(node_factory, bitcoind):
        """l1 has 5 peers, restarts, make sure we limit"""
        nodes = node_factory.get_nodes(6,
                                       opts=[{'dev-limit-connections-inflight': None, 'may_reconnect': True}] + [{'may_reconnect': True}] * 5)
    
        l1 = nodes[0]
        nodes = nodes[1:]
    
        addr = l1.rpc.newaddr()['bech32']
        for n in nodes:
            bitcoind.rpc.sendtoaddress(addr, (FUNDAMOUNT + 1000000) / 10**8)
        bitcoind.generate_block(1, wait_for_mempool=len(nodes))
        sync_blockheight(bitcoind, [l1])
    
        for n in nodes:
            l1.rpc.connect(n.info['id'], 'localhost', n.port)
            l1.rpc.fundchannel(n.info['id'], FUNDAMOUNT)
    
        # Make sure all channels are established and announced.
        bitcoind.generate_block(6, wait_for_mempool=len(nodes))
        wait_for(lambda: len(l1.rpc.listchannels()['channels']) == len(nodes) * 2)
    
        assert not l1.daemon.is_in_log('Unblocking for')
    
        l1.restart()
    
        # The first will be ok, but others should block and be unblocked.
>       l1.daemon.wait_for_logs((['Unblocking for ']
                                 + ['Too many connections, waiting'])
                                * (len(nodes) - 1))

tests/test_connection.py:4721: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <pyln.testing.utils.LightningD object at 0x7f6e288a3a60>
regexs = ['Unblocking for ', 'Too many connections, waiting', 'Unblocking for ', 'Too many connections, waiting', 'Unblocking for ', 'Too many connections, waiting', ...]
timeout = 180

    def wait_for_logs(self, regexs, timeout=TIMEOUT):
        """Look for `regexs` in the logs.
    
        The logs contain tailed stdout of the process. We look for each regex
        in `regexs`, starting from `logsearch_start` which normally is the
        position of the last found entry of a previous wait-for logs call.
        The ordering inside `regexs` doesn't matter.
    
        We fail if the timeout is exceeded or if the underlying process
        exits before all the `regexs` were found.
    
        If timeout is None, no time-out is applied.
        """
        logging.debug("Waiting for {} in the logs".format(regexs))
        exs = [re.compile(r) for r in regexs]
        start_time = time.time()
        while True:
            if self.logsearch_start >= len(self.logs):
                if not self.logs_catchup():
                    time.sleep(0.25)
    
                if timeout is not None and time.time() > start_time + timeout:
                    print("Time-out: can't find {} in logs".format(exs))
                    for r in exs:
                        if self.is_in_log(r):
                            print("({} was previously in logs!)".format(r))
>                   raise TimeoutError('Unable to find "{}" in logs.'.format(exs))
E                   TimeoutError: Unable to find "[re.compile('Unblocking for '), re.compile('Too many connections, waiting')]" in logs.
```

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2025-01-27 11:07:04 +10:30
Rusty Russell
1fffe6aa51 pytest: fix test_splice_disconnect_commit
This test seems confused: l2 won't be able to reconnect to l1 (l1
connected to l2 in the first place, it's the only one which can
reconnect).  Also, there's a commitment_signed early on when we have
dual funding, so this doesn't actually test splicing disconnect in
that case?

The race seems to happen when l1 reconnectd, and l2 hasn't registered the disconnect yet.

```
________________________ test_splice_disconnect_commit _________________________
[gw9] linux -- Python 3.10.16 /home/runner/.cache/pypoetry/virtualenvs/cln-meta-project-AqJ9wMix-py3.10/bin/python

node_factory = <pyln.testing.utils.NodeFactory object at 0x7f53ebc1a950>
bitcoind = <pyln.testing.utils.BitcoinD object at 0x7f53ebc1b760>
executor = <concurrent.futures.thread.ThreadPoolExecutor object at 0x7f53ebc1a170>

    @pytest.mark.openchannel('v1')
    @pytest.mark.openchannel('v2')
    @unittest.skipIf(TEST_NETWORK != 'regtest', 'elementsd doesnt yet support PSBT features we need')
    def test_splice_disconnect_commit(node_factory, bitcoind, executor):
        l1 = node_factory.get_node(options={'experimental-splicing': None}, may_reconnect=True)
        l2 = node_factory.get_node(disconnect=['+WIRE_COMMITMENT_SIGNED'],
                                   options={'experimental-splicing': None, 'dev-no-reconnect': None},
                                   may_reconnect=True)
>       l1.openchannel(l2, 1000000)

tests/test_splicing_disconnect.py:77: 

...
        elif "error" in resp:
>           raise RpcError(method, payload, resp['error'])
E           pyln.client.lightning.RpcError: RPC call failed: method: fundchannel, payload: {'id': '022d223620a359a47ff7f7ac447c85c46c923da53389221a0054c11c1e3ca31d59', 'amount': 1000000, 'announce': True}, error: {'code': -1, 'message': 'Disconnected', 'data': {'id': '022d223620a359a47ff7f7ac447c85c46c923da53389221a0054c11c1e3ca31d59', 'method': 'openchannel_update'}}
```

From the logs:

```
2025-01-23T23:50:25.4098040Z lightningd-2 2025-01-23T23:47:12.443Z DEBUG   0266e4598d1d3c415f572a8488830b60f7e744ed9235eb0b1ba93283b315c03518-connectd: dev_disconnect: +WIRE_COMMITMENT_SIGNED (WIRE_COMMITMENT_SIGNED)
...
2025-01-23T23:50:25.4107026Z lightningd-2 2025-01-23T23:47:12.444Z DEBUG   0266e4598d1d3c415f572a8488830b60f7e744ed9235eb0b1ba93283b315c03518-dualopend-chan#1: peer_out WIRE_COMMITMENT_SIGNED
2025-01-23T23:50:25.4108070Z lightningd-2 2025-01-23T23:47:12.444Z INFO    0266e4598d1d3c415f572a8488830b60f7e744ed9235eb0b1ba93283b315c03518-dualopend-chan#1: Peer connection lost
2025-01-23T23:50:25.4109375Z lightningd-2 2025-01-23T23:47:12.445Z INFO    0266e4598d1d3c415f572a8488830b60f7e744ed9235eb0b1ba93283b315c03518-chan#1: Peer transient failure in DUALOPEND_OPEN_COMMIT_READY: dualopend: Owning subdaemon dualopend died (62208)
...
2025-01-23T23:50:25.4111195Z lightningd-2 2025-01-23T23:47:12.445Z DEBUG   plugin-cln-grpc: Received a message: CustomNotification(Object {\"jsonrpc\": String(\"2.0\"), \"method\": String(\"channel_open_failed\"), \"params\": Object {\"channel_open_failed\": Object {\"channel_id\": String(\"252d1b0a1e57895e84137f28cf19ab2c35847e284c112fefdecc7afeaa5c1de7\")}}})
2025-01-23T23:50:25.4113039Z lightningd-2 2025-01-23T23:47:12.445Z DEBUG   plugin-cln-grpc: Dispatching custom notification Object {\"jsonrpc\": String(\"2.0\"), \"method\": String(\"channel_open_failed\"), \"params\": Object {\"channel_open_failed\": Object {\"channel_id\": String(\"252d1b0a1e57895e84137f28cf19ab2c35847e284c112fefdecc7afeaa5c1de7\")}}}
2025-01-23T23:50:25.4114525Z lightningd-2 2025-01-23T23:47:12.446Z DEBUG   plugin-funder: Cleaning up inflights for peer id 0266e4598d1d3c415f572a8488830b60f7e744ed9235eb0b1ba93283b315c03518
2025-01-23T23:50:25.4115550Z lightningd-2 2025-01-23T23:47:12.446Z DEBUG   plugin-funder: Cleaning up inflight for channel_id 252d1b0a1e57895e84137f28cf19ab2c35847e284c112fefdecc7afeaa5c1de7
2025-01-23T23:50:25.4116406Z lightningd-2 2025-01-23T23:47:12.446Z TRACE   lightningd: Calling rpc_command hook of plugin cln-xpay
2025-01-23T23:50:25.4117134Z lightningd-2 2025-01-23T23:47:12.447Z TRACE   lightningd: Plugin cln-xpay returned from rpc_command hook call
2025-01-23T23:50:25.4117728Z lightningd-1 2025-01-23T23:47:12.448Z DEBUG   connectd: drain_peer
2025-01-23T23:50:25.4118229Z lightningd-1 2025-01-23T23:47:12.448Z DEBUG   connectd: drain_peer draining subd!
2025-01-23T23:50:25.4119066Z lightningd-1 2025-01-23T23:47:12.448Z DEBUG   022d223620a359a47ff7f7ac447c85c46c923da53389221a0054c11c1e3ca31d59-lightningd: peer_disconnect_done
2025-01-23T23:50:25.4119792Z lightningd-1 2025-01-23T23:47:12.449Z DEBUG   connectd: maybe_free_peer freeing peer!
...
2025-01-23T23:50:25.4135647Z lightningd-2 2025-01-23T23:47:12.455Z DEBUG   0266e4598d1d3c415f572a8488830b60f7e744ed9235eb0b1ba93283b315c03518-connectd: Connect IN
2025-01-23T23:50:25.4136554Z lightningd-1 2025-01-23T23:47:12.455Z DEBUG   022d223620a359a47ff7f7ac447c85c46c923da53389221a0054c11c1e3ca31d59-connectd: Connected out, starting crypto
2025-01-23T23:50:25.4137502Z lightningd-1 2025-01-23T23:47:12.456Z DEBUG   022d223620a359a47ff7f7ac447c85c46c923da53389221a0054c11c1e3ca31d59-connectd: Connect OUT
2025-01-23T23:50:25.4138483Z lightningd-1 2025-01-23T23:47:12.456Z DEBUG   022d223620a359a47ff7f7ac447c85c46c923da53389221a0054c11c1e3ca31d59-connectd: peer_out WIRE_INIT
2025-01-23T23:50:25.4139407Z lightningd-1 2025-01-23T23:47:12.456Z DEBUG   022d223620a359a47ff7f7ac447c85c46c923da53389221a0054c11c1e3ca31d59-connectd: peer_in WIRE_INIT
2025-01-23T23:50:25.4140714Z lightningd-1 2025-01-23T23:47:12.456Z INFO    022d223620a359a47ff7f7ac447c85c46c923da53389221a0054c11c1e3ca31d59-chan#1: Peer transient failure in DUALOPEND_OPEN_COMMIT_READY: Disconnected
```

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2025-01-27 11:07:04 +10:30
Rusty Russell
54a5eddee7 pytest: mark xpay real gossip test as slow
```
____________________ ERROR at teardown of test_xpay_maxfee _____________________
...
            # Format a nice list of everything that went wrong and raise an exception
            request.node.has_errors = True
>           raise ValueError(str(errors))
E           ValueError: 
E           Node errors:
E            - lightningd-1: Node exited with return code 1
E           Global errors:
```

And:

```
    @unittest.skipIf(TEST_NETWORK != 'regtest', 'too dusty on elements')
    def test_xpay_maxfee(node_factory, bitcoind, chainparams):
        """Test which shows that we don't excees maxfee"""
        outfile = tempfile.NamedTemporaryFile(prefix='gossip-store-')
        subprocess.check_output(['devtools/gossmap-compress',
                                 'decompress',
                                 '--node-map=3301=022d223620a359a47ff7f7ac447c85c46c923da53389221a0054c11c1e3ca31d59',
                                 'tests/data/gossip-store-2024-09-22.compressed',
                                 outfile.name]).decode('utf-8').splitlines()
        AMOUNT = 100_000_000
    
        # l2 will warn l1 about its invalid gossip: ignore.
        # We throttle l1's gossip to avoid massive log spam.
>       l1, l2 = node_factory.line_graph(2,
                                         # This is in sats, so 1000x amount we send.
                                         fundamount=AMOUNT,
                                         opts=[{'gossip_store_file': outfile.name,
                                                'subdaemon': 'channeld:../tests/plugins/channeld_fakenet',
                                                'allow_warning': True,
                                                'dev-throttle-gossip': None},
                                               {'allow_bad_gossip': True}])

tests/test_xpay.py:509: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
contrib/pyln-testing/pyln/testing/utils.py:1720: in line_graph
    nodes = self.get_nodes(num_nodes, opts=opts)
contrib/pyln-testing/pyln/testing/utils.py:1602: in get_nodes
    return [j.result() for j in jobs]
contrib/pyln-testing/pyln/testing/utils.py:1602: in <listcomp>
    return [j.result() for j in jobs]
/opt/hostedtoolcache/Python/3.10.16/x64/lib/python3.10/concurrent/futures/_base.py:458: in result
    return self.__get_result()
/opt/hostedtoolcache/Python/3.10.16/x64/lib/python3.10/concurrent/futures/_base.py:403: in __get_result
    raise self._exception
/opt/hostedtoolcache/Python/3.10.16/x64/lib/python3.10/concurrent/futures/thread.py:58: in run
    result = self.fn(*self.args, **self.kwargs)
contrib/pyln-testing/pyln/testing/utils.py:1653: in get_node
    node.start(wait_for_bitcoind_sync)
contrib/pyln-testing/pyln/testing/utils.py:1015: in start
    self.daemon.start(stderr_redir=stderr_redir)
contrib/pyln-testing/pyln/testing/utils.py:671: in start
    self.wait_for_log("Server started with public key")
contrib/pyln-testing/pyln/testing/utils.py:355: in wait_for_log
    return self.wait_for_logs([regex], timeout)
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <pyln.testing.utils.LightningD object at 0x7f27ab586c20>
regexs = ['Server started with public key'], timeout = 180

    def wait_for_logs(self, regexs, timeout=TIMEOUT):
        """Look for `regexs` in the logs.
    
        The logs contain tailed stdout of the process. We look for each regex
        in `regexs`, starting from `logsearch_start` which normally is the
        position of the last found entry of a previous wait-for logs call.
        The ordering inside `regexs` doesn't matter.
    
        We fail if the timeout is exceeded or if the underlying process
        exits before all the `regexs` were found.
    
        If timeout is None, no time-out is applied.
        """
        logging.debug("Waiting for {} in the logs".format(regexs))
        exs = [re.compile(r) for r in regexs]
        start_time = time.time()
        while True:
            if self.logsearch_start >= len(self.logs):
                if not self.logs_catchup():
                    time.sleep(0.25)
    
                if timeout is not None and time.time() > start_time + timeout:
                    print("Time-out: can't find {} in logs".format(exs))
                    for r in exs:
                        if self.is_in_log(r):
                            print("({} was previously in logs!)".format(r))
>                   raise TimeoutError('Unable to find "{}" in logs.'.format(exs))
E                   TimeoutError: Unable to find "[re.compile('Server started with public key')]" in logs.
```

gossipd (and other plugins) simply take too long to digest the gossmap under valgrind.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2025-01-27 11:07:04 +10:30
Rusty Russell
84b64d9073 pytest: fix flake in tests/test_connection.py::test_reconnect_signed
Sometimes, l1 wouldn't receive the msg before l2 hung up, causing
chaos.  What we *actually* want here is to make sure that l1 receives
the msg before closing:

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

tests/test_connection.py:667: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
contrib/pyln-client/pyln/client/lightning.py:767: in fundchannel
    return self.call("fundchannel", payload)
contrib/pyln-testing/pyln/testing/utils.py:740: in call
    res = LightningRpc.call(self, method, payload, cmdprefix, filter)
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <pyln.testing.utils.PrettyPrintingLightningRpc object at 0x7f22112f5450>
method = 'fundchannel'
payload = {'amount': 50000, 'announce': True, 'id': '022d223620a359a47ff7f7ac447c85c46c923da53389221a0054c11c1e3ca31d59'}
cmdprefix = None, filter = None

    def call(self, method, payload=None, cmdprefix=None, filter=None):
        """Generic call API: you can set cmdprefix here, or set self.cmdprefix
        before the call is made.
    
        """
        self.logger.debug("Calling %s with payload %r", method, payload)
    
        if payload is None:
            payload = {}
        # Filter out arguments that are None
        if isinstance(payload, dict):
            payload = {k: v for k, v in payload.items() if v is not None}
    
        this_id = self.get_json_id(method, cmdprefix)
        self.next_id += 1
    
        # FIXME: we open a new socket for every readobj call...
        sock = UnixSocket(self.socket_path)
    
        buf = b''
    
        if self._notify is not None:
            # Opt into the notifications support
            self._writeobj(sock, {
                "jsonrpc": "2.0",
                "method": "notifications",
                "id": this_id + "+notify-enable",
                "params": {
                    "enable": True
                },
            })
            # FIXME: Notification schema support?
            _, buf = self._readobj(sock, buf)
    
        request = {
            "jsonrpc": "2.0",
            "method": method,
            "params": payload,
            "id": this_id,
        }
    
        if filter is None:
            filter = self._filter
        if filter is not None:
            request["filter"] = filter
    
        self._writeobj(sock, request)
        while True:
            resp, buf = self._readobj(sock, buf)
            id = resp.get("id", None)
            meth = resp.get("method", None)
    
            if meth == 'message' and self._notify is not None:
                n = resp['params']
                self._notify(
                    message=n.get('message', None),
                    progress=n.get('progress', None),
                    request=request
                )
                continue
    
            if meth is None or id is None:
                break
    
        self.logger.debug("Received response for %s call: %r", method, resp)
        if 'id' in resp and resp['id'] != this_id:
            raise ValueError("Malformed response, id is not {}: {}.".format(this_id, resp))
        sock.close()
    
        if not isinstance(resp, dict):
            raise TypeError("Malformed response, response is not a dictionary %s." % resp)
        elif "error" in resp:
>           raise RpcError(method, payload, resp['error'])
E           pyln.client.lightning.RpcError: RPC call failed: method: fundchannel, payload: {'id': '022d223620a359a47ff7f7ac447c85c46c923da53389221a0054c11c1e3ca31d59', 'amount': 50000, 'announce': True}, error: {'code': -1, 'message': 'Disconnected', 'data': {'id': '022d223620a359a47ff7f7ac447c85c46c923da53389221a0054c11c1e3ca31d59', 'method': 'openchannel_update'}}
```

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2025-01-27 11:07:04 +10:30
Rusty Russell
5ae183b49b connectd: attach input filtering for incoming dev_disconnect.
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2025-01-27 11:07:04 +10:30
Rusty Russell
7556164e58 dev_disconnect: add '<' to close after an incoming msg.
I'd been resisting this, but some tests really do want "hang up after
*receiving* this", and it's more reliable than getting the peer to
"hang up afer *sending* this" which seems not always work.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2025-01-27 11:07:04 +10:30
Rusty Russell
44c6a22e5f dev_disconnect: rename to dev_disconnect_out, in preparation for incoming filters.
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2025-01-27 11:07:04 +10:30
Rusty Russell
e3a08b315d pytest: fix flake in test_no_reconnect_awating_unilateral
```
    def test_no_reconnect_awating_unilateral(node_factory, bitcoind):
        l1, l2 = node_factory.line_graph(2, opts={'may_reconnect': True})
        l2.stop()
    
        # Close immediately.
        l1.rpc.close(l2.info['id'], 1)
    
        wait_for(lambda: only_one(l1.rpc.listpeerchannels(l2.info['id'])['channels'])['state'] == 'AWAITING_UNILATERAL')
    
        # After switching to AWAITING_UNILATERAL it will *not* try to reconnect.
        l1.daemon.wait_for_log("State changed from CHANNELD_SHUTTING_DOWN to AWAITING_UNILATERAL")
        time.sleep(10)
    
>       assert not l1.daemon.is_in_log('Will try reconnect', start=l1.daemon.logsearch_start)
E       AssertionError: assert not 'lightningd-1 2025-01-20T05:46:04.548Z DEBUG   022d223620a359a47ff7f7ac447c85c46c923da53389221a0054c11c1e3ca31d59-connectd: Will try reconnect in 2 seconds'
E        +  where 'lightningd-1 2025-01-20T05:46:04.548Z DEBUG   022d223620a359a47ff7f7ac447c85c46c923da53389221a0054c11c1e3ca31d59-connectd: Will try reconnect in 2 seconds' = <bound method TailableProc.is_in_log of <pyln.testing.utils.LightningD object at 0x7f68ab565c90>>('Will try reconnect', start=453)
E        +    where <bound method TailableProc.is_in_log of <pyln.testing.utils.LightningD object at 0x7f68ab565c90>> = <pyln.testing.utils.LightningD object at 0x7f68ab565c90>.is_in_log
E        +      where <pyln.testing.utils.LightningD object at 0x7f68ab565c90> = <fixtures.LightningNode object at 0x7f68ab567880>.daemon
E        +    and   453 = <pyln.testing.utils.LightningD object at 0x7f68ab565c90>.logsearch_start
E        +      where <pyln.testing.utils.LightningD object at 0x7f68ab565c90> = <fixtures.LightningNode object at 0x7f68ab567880>.daemon
```

In fact:

```
2025-01-20T06:15:27.2854309Z lightningd-2 2025-01-20T05:46:03.527Z DEBUG   lightningd: io_break: destroy_plugin
2025-01-20T06:15:27.2855089Z lightningd-2 2025-01-20T05:46:03.527Z DEBUG   lightningd: Command returned result after jcon close
2025-01-20T06:15:27.2855805Z lightningd-2 2025-01-20T05:46:03.528Z DEBUG   connectd: Shutting down
2025-01-20T06:15:27.2856576Z lightningd-2 2025-01-20T05:46:03.528Z DEBUG   gossipd: Shutting down
2025-01-20T06:15:27.2857159Z lightningd-1 2025-01-20T05:46:03.529Z DEBUG   connectd: drain_peer
2025-01-20T06:15:27.2857790Z lightningd-1 2025-01-20T05:46:03.529Z DEBUG   connectd: drain_peer draining subd!
2025-01-20T06:15:27.2858825Z lightningd-1 2025-01-20T05:46:03.529Z DEBUG   022d223620a359a47ff7f7ac447c85c46c923da53389221a0054c11c1e3ca31d59-lightningd: peer_disconnect_done
2025-01-20T06:15:27.2860481Z lightningd-1 2025-01-20T05:46:03.529Z DEBUG   022d223620a359a47ff7f7ac447c85c46c923da53389221a0054c11c1e3ca31d59-connectd: Will try reconnect in 1 seconds
2025-01-20T06:15:27.2861626Z lightningd-1 2025-01-20T05:46:03.529Z DEBUG   connectd: maybe_free_peer freeing peer!
2025-01-20T06:15:27.2862723Z lightningd-1 2025-01-20T05:46:03.530Z INFO    022d223620a359a47ff7f7ac447c85c46c923da53389221a0054c11c1e3ca31d59-channeld-chan#1: Peer connection lost
2025-01-20T06:15:27.2864510Z lightningd-1 2025-01-20T05:46:03.530Z INFO    022d223620a359a47ff7f7ac447c85c46c923da53389221a0054c11c1e3ca31d59-chan#1: Peer transient failure in CHANNELD_NORMAL: channeld: Owning subdaemon channeld died (62208)
2025-01-20T06:15:27.2866301Z lightningd-1 2025-01-20T05:46:03.530Z DEBUG   plugin-funder: Cleaning up inflights for peer id 022d223620a359a47ff7f7ac447c85c46c923da53389221a0054c11c1e3ca31d59
2025-01-20T06:15:27.2867313Z lightningd-2 2025-01-20T05:46:03.530Z DEBUG   hsmd: Shutting down
2025-01-20T06:15:27.2868029Z lightningd-1 2025-01-20T05:46:03.535Z TRACE   lightningd: Calling rpc_command hook of plugin cln-xpay
2025-01-20T06:15:27.2868935Z lightningd-1 2025-01-20T05:46:03.535Z TRACE   lightningd: Plugin cln-xpay returned from rpc_command hook call
2025-01-20T06:15:27.2869830Z lightningd-1 2025-01-20T05:46:03.536Z TRACE   lightningd: Calling rpc_command hook of plugin cln-xpay
2025-01-20T06:15:27.2870740Z lightningd-1 2025-01-20T05:46:03.536Z TRACE   lightningd: Plugin cln-xpay returned from rpc_command hook call
2025-01-20T06:15:27.2872276Z lightningd-1 2025-01-20T05:46:03.536Z INFO    022d223620a359a47ff7f7ac447c85c46c923da53389221a0054c11c1e3ca31d59-chan#1: State changed from CHANNELD_NORMAL to CHANNELD_SHUTTING_DOWN
2025-01-20T06:15:27.2873873Z lightningd-1 2025-01-20T05:46:03.538Z DEBUG   lightningd: NOTIFY "-c:close#30" info peer is offline, will negotiate once they reconnect (1 seconds before unilateral close).
2025-01-20T06:15:27.2874947Z lightningd-1 2025-01-20T05:46:03.538Z DEBUG   lightningd: close_command: timeout = 1
2025-01-20T06:15:27.2878248Z lightningd-1 2025-01-20T05:46:03.541Z DEBUG   plugin-cln-grpc: Received a message: CustomNotification(Object {\"jsonrpc\": String(\"2.0\"), \"method\": String(\"channel_state_changed\"), \"params\": Object {\"channel_state_changed\": Object {\"cause\": String(\"user\"), \"channel_id\": String(\"9aeb0e78b23e67f13670c602d5a40a7c8482a87220d93522cc0f7c6c9da9daab\"), \"message\": String(\"User or plugin invoked close command\"), \"new_state\": String(\"CHANNELD_SHUTTING_DOWN\"), \"old_state\": String(\"CHANNELD_NORMAL\"), \"peer_id\": String(\"022d223620a359a47ff7f7ac447c85c46c923da53389221a0054c11c1e3ca31d59\"), \"short_channel_id\": String(\"103x1x0\"), \"timestamp\": String(\"2025-01-20T05:46:03.537Z\")}}})
2025-01-20T06:15:27.2884122Z lightningd-1 2025-01-20T05:46:03.542Z DEBUG   plugin-cln-grpc: Dispatching custom notification Object {\"jsonrpc\": String(\"2.0\"), \"method\": String(\"channel_state_changed\"), \"params\": Object {\"channel_state_changed\": Object {\"cause\": String(\"user\"), \"channel_id\": String(\"9aeb0e78b23e67f13670c602d5a40a7c8482a87220d93522cc0f7c6c9da9daab\"), \"message\": String(\"User or plugin invoked close command\"), \"new_state\": String(\"CHANNELD_SHUTTING_DOWN\"), \"old_state\": String(\"CHANNELD_NORMAL\"), \"peer_id\": String(\"022d223620a359a47ff7f7ac447c85c46c923da53389221a0054c11c1e3ca31d59\"), \"short_channel_id\": String(\"103x1x0\"), \"timestamp\": String(\"2025-01-20T05:46:03.537Z\")}}}
2025-01-20T06:15:27.2888242Z lightningd-1 2025-01-20T05:46:03.542Z DEBUG   plugin-cln-grpc: Failed to parse notification from lightningd Error(\"unknown variant `channel_state_changed`, expected one of `block_added`, `channel_open_failed`, `channel_opened`, `connect`, `custommsg`\", line: 0, column: 0)
2025-01-20T06:15:27.2889970Z lightningd-1 2025-01-20T05:46:04.350Z DEBUG   gossipd: seeker: no peers, waiting
2025-01-20T06:15:27.2890762Z lightningd-1 2025-01-20T05:46:04.538Z DEBUG   lightningd: NOTIFY "-c:close#30" info Timed out, forcing close.
2025-01-20T06:15:27.2892345Z lightningd-1 2025-01-20T05:46:04.539Z UNUSUAL 022d223620a359a47ff7f7ac447c85c46c923da53389221a0054c11c1e3ca31d59-chan#1: Peer permanent failure in CHANNELD_SHUTTING_DOWN: Forcibly closed by `close` command timeout (reason=user)
2025-01-20T06:15:27.2894333Z lightningd-1 2025-01-20T05:46:04.539Z INFO    022d223620a359a47ff7f7ac447c85c46c923da53389221a0054c11c1e3ca31d59-chan#1: State changed from CHANNELD_SHUTTING_DOWN to AWAITING_UNILATERAL
2025-01-20T06:15:27.2895943Z lightningd-1 2025-01-20T05:46:04.543Z DEBUG   022d223620a359a47ff7f7ac447c85c46c923da53389221a0054c11c1e3ca31d59-chan#1: We have 1 anchor points to use
2025-01-20T06:15:27.2897412Z lightningd-1 2025-01-20T05:46:04.544Z DEBUG   lightningd: Broadcasting txid c96f6e4409140474fdd5d8b4862c3d74bd6fa24dadd178182e78fdc4cbf68149 for "-c:close#30"
2025-01-20T06:15:27.2906272Z lightningd-1 2025-01-20T05:46:04.544Z DEBUG   lightningd: sendrawtransaction: 020000000001019aeb0e78b23e67f13670c602d5a40a7c8482a87220d93522cc0f7c6c9da9daab00000000009db0e280024a01000000000000220020be7935a77ca9ab70a4b8b1906825637767fed3c00824aa90c988983587d68488352f0f00000000002200209f4684ddb28acdc73959bc194d1a25df906f61ed030f52d163e6f1e247d32cbb0400473044022061656b7587a96723e3942f7445313d1c4315e8b2a17fade62d9a48d8a69e2806022024ac01825c79d3bcee6f5dc19586af6b3f8415156cbda934d0e2cbad9268a6a20147304402201fb54f5cb72da9dfd1399b8df6bf4f1950313b057fc0f5b30b2b09aec2783c9e022052dbd5e30bdc7015c0eb939ff3ad58b83c2d7369bb546571603ccfa62e65c4e00147522102324266de8403b3ab157a09f1f784d587af61831c998c151bcc21bb74c2b2314b2102e3bd38009866c9da8ec4aa99cc4ea9c6c0dd46df15c61ef0ce1f271291714e5752ae9a3ed620
2025-01-20T06:15:27.2914366Z lightningd-1 2025-01-20T05:46:04.548Z DEBUG   hsmd: Client: Received message 5 from client
2025-01-20T06:15:27.2915958Z lightningd-1 2025-01-20T05:46:04.548Z DEBUG   022d223620a359a47ff7f7ac447c85c46c923da53389221a0054c11c1e3ca31d59-connectd: Failed connected out: All addresses failed: 127.0.0.1:42595: Connection establishment: Connection refused. 
2025-01-20T06:15:27.2917891Z lightningd-1 2025-01-20T05:46:04.548Z DEBUG   022d223620a359a47ff7f7ac447c85c46c923da53389221a0054c11c1e3ca31d59-connectd: Will try reconnect in 2 seconds
2025-01-20T06:15:27.2921924Z lightningd-1 2025-01-20T05:46:04.548Z DEBUG   plugin-cln-grpc: Received a message: CustomNotification(Object {\"jsonrpc\": String(\"2.0\"), \"method\": String(\"channel_state_changed\"), \"params\": Object {\"channel_state_changed\": Object {\"cause\": String(\"user\"), \"channel_id\": String(\"9aeb0e78b23e67f13670c602d5a40a7c8482a87220d93522cc0f7c6c9da9daab\"), \"message\": String(\"Forcibly closed by `close` command timeout\"), \"new_state\": String(\"AWAITING_UNILATERAL\"), \"old_state\": String(\"CHANNELD_SHUTTING_DOWN\"), \"peer_id\": String(\"022d223620a359a47ff7f7ac447c85c46c923da53389221a0054c11c1e3ca31d59\"), \"short_channel_id\": String(\"103x1x0\"), \"timestamp\": String(\"2025-01-20T05:46:04.540Z\")}}})
2025-01-20T06:15:27.2928311Z lightningd-1 2025-01-20T05:46:04.548Z DEBUG   plugin-cln-grpc: Dispatching custom notification Object {\"jsonrpc\": String(\"2.0\"), \"method\": String(\"channel_state_changed\"), \"params\": Object {\"channel_state_changed\": Object {\"cause\": String(\"user\"), \"channel_id\": String(\"9aeb0e78b23e67f13670c602d5a40a7c8482a87220d93522cc0f7c6c9da9daab\"), \"message\": String(\"Forcibly closed by `close` command timeout\"), \"new_state\": String(\"AWAITING_UNILATERAL\"), \"old_state\": String(\"CHANNELD_SHUTTING_DOWN\"), \"peer_id\": String(\"022d223620a359a47ff7f7ac447c85c46c923da53389221a0054c11c1e3ca31d59\"), \"short_channel_id\": String(\"103x1x0\"), \"timestamp\": String(\"2025-01-20T05:46:04.540Z\")}}}
2025-01-20T06:15:27.2932905Z lightningd-1 2025-01-20T05:46:04.549Z DEBUG   plugin-cln-grpc: Failed to parse notification from lightningd Error(\"unknown variant `channel_state_changed`, expected one of `block_added`, `channel_open_failed`, `channel_opened`, `connect`, `custommsg`\", line: 0, column: 0)
2025-01-20T06:15:27.2934604Z lightningd-1 2025-01-20T05:46:04.549Z TRACE   lightningd: Calling rpc_command hook of plugin cln-xpay
2025-01-20T06:15:27.2935599Z lightningd-1 2025-01-20T05:46:04.551Z TRACE   lightningd: Plugin cln-xpay returned from rpc_command hook call
2025-01-20T06:15:27.2936589Z lightningd-1 2025-01-20T05:46:04.553Z TRACE   lightningd: Calling rpc_command hook of plugin cln-xpay
2025-01-20T06:15:27.2937546Z lightningd-1 2025-01-20T05:46:04.554Z TRACE   lightningd: Plugin cln-xpay returned from rpc_command hook call
2025-01-20T06:15:27.2946767Z lightningd-1 2025-01-20T05:46:04.581Z DEBUG   plugin-bcli: sendrawtx exit 0 (bitcoin-cli -regtest -datadir=/tmp/ltests-qdo6i210/test_no_reconnect_awating_unilateral_1/lightning-1/ -rpcclienttimeout=60 -rpcport=57415 -rpcuser=... -stdinrpcpass sendrawtransaction 020000000001019aeb0e78b23e67f13670c602d5a40a7c8482a87220d93522cc0f7c6c9da9daab00000000009db0e280024a01000000000000220020be7935a77ca9ab70a4b8b1906825637767fed3c00824aa90c988983587d68488352f0f00000000002200209f4684ddb28acdc73959bc194d1a25df906f61ed030f52d163e6f1e247d32cbb0400473044022061656b7587a96723e3942f7445313d1c4315e8b2a17fade62d9a48d8a69e2806022024ac01825c79d3bcee6f5dc19586af6b3f8415156cbda934d0e2cbad9268a6a20147304402201fb54f5cb72da9dfd1399b8df6bf4f1950313b057fc0f5b30b2b09aec2783c9e022052dbd5e30bdc7015c0eb939ff3ad58b83c2d7369bb546571603ccfa62e65c4e00147522102324266de8403b3ab157a09f1f784d587af61831c998c151bcc21bb74c2b2314b2102e3bd38009866c9da8ec4aa99cc4ea9c6c0dd46df15c61ef0ce1f271291714e5752ae9a3ed620) 
2025-01-20T06:15:27.2956874Z lightningd-1 2025-01-20T05:46:04.581Z DEBUG   022d223620a359a47ff7f7ac447c85c46c923da53389221a0054c11c1e3ca31d59-chan#1: Low-priority anchorspend aiming for block 2119 (feerate 253)
2025-01-20T06:15:27.2958216Z lightningd-1 2025-01-20T05:46:04.583Z DEBUG   hsmd: Client: Received message 28 from client
2025-01-20T06:15:27.2958970Z lightningd-1 2025-01-20T05:46:09.354Z DEBUG   gossipd: seeker: no peers, waiting
2025-01-20T06:15:27.2959764Z lightningd-1 2025-01-20T05:46:09.568Z DEBUG   lightningd: channel_gossip: no longer in startup mode
2025-01-20T06:15:27.2960572Z lightningd-1 2025-01-20T05:46:14.358Z DEBUG   gossipd: seeker: no peers, waiting
2025-01-20T06:15:27.2962896Z {'github_repository': 'ElementsProject/lightning', 'github_sha': '8c945c6075752c2488c211f912e9b97d1d019fc5', 'github_ref': 'refs/pull/7886/merge', 'github_ref_name': 'HEAD', 'github_run_id': 12859491513, 'github_head_ref': 'guilt/test-htable', 'github_run_number': 11999, 'github_base_ref': 'master', 'github_run_attempt': '3', 'testname': 'test_no_reconnect_awating_unilateral', 'start_time': 1737351957, 'end_time': 1737351974, 'outcome': 'fail'}
2025-01-20T06:15:27.2965150Z --------------------------- Captured stdout teardown ---------------------------
```

We need to check that connectd got the "peer_downgrade" message: before that it *might* try to connect.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2025-01-27 11:07:04 +10:30
Alex Myers
0c6aa38bd5 github: update PR template with 25.02 freeze cutoff date.
Changelog-None
2025-01-25 11:06:11 +10:30
ShahanaFarooqui
7460b7dc7f tests: Add logger config with fixture
Pyln logger's configuration was unexpectedly being overwritten by the root logger during the autogenerated examples test, complicating error debugging.

We resolved this by introducing a pytest fixture to reapply the logger configuration before the tests executes.

Changelog-None.

Fixes: https://github.com/ElementsProject/lightning/issues/8023
2025-01-24 17:00:03 +10:30
ShahanaFarooqui
32a991acaf ci: Send email if the reproducible build process fails
Changelog-None.
2025-01-24 16:52:56 +10:30
ShahanaFarooqui
14dfaac6ed gpg: Add gpg public key for cln@blockstream.com
Changelog-None.
2025-01-24 16:51:54 +10:30
fanquake
305c377985 build: fix linking to libsodium on macOS
Currently on I see link failures like the following:
```bash
./configure
<snip>
checking for libsodium with IETF chacha20 variants... yes
<snip>
ar libccan.a
ld ccan/ccan/cdump/tools/cdump-enumstr
ld: library 'sodium' not found
clang: error: linker command failed with exit code 1 (use -v to see invocation)
```

The configure check passes under Clang here.

Changelog-Fixed: build: fix linking against libsodium on macOS.
2025-01-23 10:10:09 +10:30
fanquake
f054b3b8b9 build: fixup check for HAVE_GOOD_LIBSODIUM
The current check fails when building with newer GCC, i.e:
```bash
error: ‘crypto_secretstream_xchacha20poly1305_init_push’ reading 32 bytes from a region of size 3 [-Werror=stringop-overread]
   12 |         crypto_secretstream_xchacha20poly1305_init_push(&crypto_state, header,
      |         ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   13 |                                                         data);
```

This inadvertently results in the release binaries for Ubuntu 22.04 &
24.04, not having a runtime libsodium dependency, but instead using the
bundled lib.

It's not clear to me this is actually enough to fix (all) the release builds,
as the build containers need to have `libsodium-dev`, not just `libsodium`
in them, and it's not clear to me which packages are actually present
looking at the repro build scripts.

Changelog-Fixed: build: libsodium configure check fixed to work with newer GCC.
2025-01-23 10:09:25 +10:30
michael1011
54ee08b5c5 xpay: fix description of description of bias 2025-01-22 12:19:47 -08:00
michael1011
060368bb0a xpay: add maxdelay parameter
Changelog-Added: Plugins: `xpay` now supports a `maxdelay` parameter for better `xpay-handle-pay` compatibility.
2025-01-22 12:19:47 -08:00
Rusty Russell
b6c1ffa359 ccan/htable: update to explicit DUPS/NODUPS types.
The updated API requires typed htables to explicitly state whether they
allow duplicates: for most cases we don't, but we've had issues in the
past.

This is a big patch, but mainly mechanical.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2025-01-21 09:18:25 +10:30
Rusty Russell
5cecdd7dba common: add test for htable churn.
I wanted to make sure we didn't have a bug in our htable routine,
so I wrote this test.  We don't, but leave it in.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2025-01-21 09:18:25 +10:30
Rusty Russell
d6217e2835 wallet: do proper memleak scan of outpoint htables, not notleak().
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2025-01-21 09:18:25 +10:30
ShahanaFarooqui
2f64283945 github: Checkout action triggering branch
To ensure the workflow uses updated files, including the Dockerfile, from the same branch for testing.
2025-01-15 10:36:43 -08:00
Se7enZ
0129aecda8 build: Update poetry.lock files for CLN and built-in plugins
Main application poetry.lock file as well as clnrest and wss-proxy.
2025-01-15 10:36:43 -08:00
Se7enZ
72df375503 chore(docker): Update support for Poetry v2.0.0.
- Install `poetry-plugin-export` as a separate step.
- Remove `--no-update` option from `poetry lock` as it's now default behavior.
- Add `poetry lock` to the command chain after removing cln-rest and wss-proxy.

https://github.com/python-poetry/poetry/releases/tag/2.0.0
2025-01-15 10:36:43 -08:00
Se7enZ
8a0771d081 chore(docker): Clean up formatting and standardize Dockerfile.
- Align indentation.
- Use multi-line `ENV` where values don't depend on each other.

Changelog-None
2025-01-15 10:36:43 -08:00
Se7enZ
ec364deeda build: Upgrade Docker base images to Debian Bookworm.
Undertaken to upgrade QEMU to 7.2. Also upgrades Python to 3.11
implicitly and migrates Python dependency management to virtual environments.

Changelog-Changed: Released Docker images are now based on Debian Bookworm
2025-01-15 10:36:43 -08:00
Se7enZ
4329a194ae build: Fixes for the Docker building libpq lib.
- Add Postgres dependencies: bison, flex and libiu-dev.
- Fix missing `&&` in chained wget commands.
- Add `POSTGRES_CONFIG` and `PG_CONFIG` for all architectures.
- Remove existing `libpq` Ubuntu packages.
- Copy libpq libraries from builder directly to final image.

Changelog-Fixed: Fixes Postgres driver availability for arm64 and arm32 Docker images.
2025-01-15 10:36:43 -08:00
arowser
07c1a7f4fe docker: add libpq for multi-arch build configuration 2025-01-15 10:36:43 -08:00
fanquake
9ce885b8a1 ci: remove macOS gettext symlinking
This doesn't do anything, because it's trying to create a symlink for a
verison that doesn't exist. The version installed via brew is 0.22.5.

In any case, on any recent macOS system, this should not be necessary.

Changelog-None.
2025-01-13 19:53:20 -08:00
ShahanaFarooqui
24e0929c0e tools: Add testnet4 support for reckless and hsmtool
Changelog-Added: Support for Bitcoin `testnet4`
2025-01-13 15:45:19 -08:00
ShahanaFarooqui
e731170cc9 tests: Add testnet4 default port 2025-01-13 15:45:19 -08:00
ShahanaFarooqui
f640394ceb doc: Add details and script check for testnet4 2025-01-13 15:45:19 -08:00
ShahanaFarooqui
02b19a8796 pyln-spec: add testnet4 support 2025-01-13 15:45:19 -08:00
2seaq
1da0c1fbe2 common: Chainparams for testnet4 support
The BIP70 name given as testnet4 to correspond with chaininfo value.
2025-01-13 15:45:19 -08:00
ShahanaFarooqui
c1484a65c2 ci: Fix for FreeBSD workflow
Changelog-None.
2025-01-13 12:36:51 -08:00
ShahanaFarooqui
219623c8d7 tests: Reckless test fix for project must contain name
Fix for `The Poetry configuration is invalid:  - project must contain ['name'] properties`
2025-01-09 11:15:05 +01:00
ShahanaFarooqui
740b7125de ci: Install poetry-plugin-export for poetry export command
Poetry will no longer include the `poetry-plugin-export` plugin by default, which is essential for exporting dependencies. So, we now need to install it explicitly.
2025-01-09 11:15:05 +01:00
ShahanaFarooqui
127ceb6ddb ci: Lock MacOS and poetry versions 2025-01-09 11:15:05 +01:00
ShahanaFarooqui
9c34bd6108 ci: Lock Ubuntu version on 22.04
These workflows are failing due to `ubuntu-latest` being updated from version `22.04` to `24.04`.

Reference: https://github.com/actions/runner-images/issues/10636

Changelog-None.
2025-01-09 11:15:05 +01:00
Rusty Russell
98679aa6cf pytest: fix flake in test_restorefrompeer.
Just because we've seen the block doesn't mean onchaind has finished
starting up.

```
 _____________________________ test_restorefrompeer _____________________________
[gw0] linux -- Python 3.10.15 /home/runner/.cache/pypoetry/virtualenvs/cln-meta-project-AqJ9wMix-py3.10/bin/python

node_factory = <pyln.testing.utils.NodeFactory object at 0x7fb8f3887f70>
bitcoind = <pyln.testing.utils.BitcoinD object at 0x7fb8f3886f50>

    @unittest.skipIf(os.getenv('TEST_DB_PROVIDER', 'sqlite3') != 'sqlite3', "deletes database, which is assumed sqlite3")
    def test_restorefrompeer(node_factory, bitcoind):
        """
        Test restorefrompeer
        """
        l1, l2 = node_factory.get_nodes(2, [{'broken_log': 'ERROR: Unknown commitment #.*, recovering our funds!',
                                             'experimental-peer-storage': None,
                                             'may_reconnect': True,
                                             'allow_bad_gossip': True},
                                            {'experimental-peer-storage': None,
                                             'may_reconnect': True}])
    
        l1.rpc.connect(l2.info['id'], 'localhost', l2.port)
    
        c12, _ = l1.fundchannel(l2, 10**5)
        assert l1.daemon.is_in_log('Peer storage sent!')
        assert l2.daemon.is_in_log('Peer storage sent!')
    
        l1.stop()
        os.unlink(os.path.join(l1.daemon.lightning_dir, TEST_NETWORK, "lightningd.sqlite3"))
    
        l1.start()
        assert l1.daemon.is_in_log('Server started with public key')
    
        # If this happens fast enough, connect fails with "disconnected
        # during connection"
        try:
            l1.rpc.connect(l2.info['id'], 'localhost', l2.port)
        except RpcError as err:
            assert "disconnected during connection" in err.error['message']
    
        l1.daemon.wait_for_log('peer_in WIRE_YOUR_PEER_STORAGE')
    
        assert l1.rpc.restorefrompeer()['stubs'][0] == _['channel_id']
    
        l1.daemon.wait_for_log('peer_out WIRE_ERROR')
        l2.daemon.wait_for_log('State changed from CHANNELD_NORMAL to AWAITING_UNILATERAL')
    
        bitcoind.generate_block(5, wait_for_mempool=1)
        sync_blockheight(bitcoind, [l1, l2])
    
        l1.daemon.wait_for_log(r'All outputs resolved.*')
        wait_for(lambda: l1.rpc.listfunds()["channels"][0]["state"] == "ONCHAIN")
    
        # Check if funds are recovered.
        assert l1.rpc.listfunds()["channels"][0]["state"] == "ONCHAIN"
>       assert l2.rpc.listfunds()["channels"][0]["state"] == "ONCHAIN"
E       AssertionError: assert 'FUNDING_SPEND_SEEN' == 'ONCHAIN'
E         - ONCHAIN
E         + FUNDING_SPEND_SEEN

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

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-12-20 15:36:07 +10:30
Rusty Russell
9758b05bd0 pytest: fix flake in test_penalty_htlc_tx_fulfill
Make sure balancing payment is fully cleared before trying to get a routeL

```
    def test_penalty_htlc_tx_fulfill(node_factory, bitcoind, chainparams, anchors):

        # now we send one 'sticky' htlc: l4->l1
        amt = 10**8 // 2
        sticky_inv = l1.rpc.invoice(amt, '2', 'sticky')
>       route = l4.rpc.getroute(l1.info['id'], amt, 1)['route']

tests/test_closing.py:1232:

>           raise RpcError(method, payload, resp['error'])
E           pyln.client.lightning.RpcError: RPC call failed: method: getroute, payload: {'id': '0266e4598d1d3c415f572a8488830b60f7e744ed9235eb0b1ba93283b315c03518', 'amount_msat': 50000000, 'riskfactor': 1, 'cltv': 9}, error: {'code': 205, 'message': 'Could not find a route'}
```
2024-12-20 15:36:07 +10:30
Rusty Russell
69bfa6f5b1 channeld_fakenet: don't be as brute-force trying to derive keys.
Keep a proper cache of all possible ones.  I think this may be the
timeout problem: according to the logs, channeld_fakenet stops responding
and thus HTLCs eventually time out.

```
```
2024-12-16T23:16:16.4874420Z lightningd-1 2024-12-16T22:45:14.068Z UNUSUAL 022d223620a359a47ff7f7ac447c85c46c923da53389221a0054c11c1e3ca31d59-channeld-chan#1: Adding HTLC 18446744073709551615 too slow: killing connection
```

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-12-20 15:36:07 +10:30
Rusty Russell
4b283eb96e pytest: fix flake in test_gossip_throttle
We can get the reply_short_channel_ids_end in the messages when
we make a query:

```
2024-11-29T07:39:28.8550652Z         time_fast = time.time() - start_fast
2024-11-29T07:39:28.8551067Z         assert time_fast < 2
2024-11-29T07:39:28.8551487Z         out3 = [m for m in out3 if not m.startswith(b'0109')]
2024-11-29T07:39:28.8552158Z >       assert set(out1) == set(out3)
...
2024-11-29T07:39:28.8675516Z E         Extra items in the right set:
2024-11-29T07:39:28.8675887Z E         b'010606226e46111a0b59caaf126043eb5bbf28c34f3a5e332a1fc7b2b73cf188910f01'
```

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-12-20 15:36:07 +10:30
Rusty Russell
3a0e3a1591 pytest: fix test in test_gossip_pruning
It's possible that listchannels doesn't show the channel yet:

```
    
        l1.rpc.connect(l2.info['id'], 'localhost', l2.port)
        l2.rpc.connect(l3.info['id'], 'localhost', l3.port)
    
        scid1, _ = l1.fundchannel(l2, 10**6)
        scid2, _ = l2.fundchannel(l3, 10**6)
    
        mine_funding_to_announce(bitcoind, [l1, l2, l3])
>       l1_initial_cupdate_timestamp = only_one(l1.rpc.listchannels(source=l1.info['id'])['channels'])['last_update']

tests/test_gossip.py:43: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

arr = []

    def only_one(arr):
        """Many JSON RPC calls return an array; often we only expect a single entry
        """
>       assert len(arr) == 1
E       AssertionError
```

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-12-20 15:36:07 +10:30
Rusty Russell
e998a72ef6 lightningd: fix overzealous memleak detection in json_add_datastore.
The lifetime is bound to the response, but memleak gets upset if it
sees it.  Use the standard take() pattern insteas.

```
lightningd-5 2024-11-28T05:02:27.503Z **BROKEN** lightningd: MEMLEAK: 0x55b58f329338
lightningd-5 2024-11-28T05:02:27.503Z **BROKEN** lightningd:   label=common/utils.c:150:char[]
lightningd-5 2024-11-28T05:02:27.504Z **BROKEN** lightningd:   alloc:
lightningd-5 2024-11-28T05:02:27.585Z **BROKEN** lightningd:     ccan/ccan/tal/tal.c:488 (tal_alloc_)
lightningd-5 2024-11-28T05:02:27.586Z **BROKEN** lightningd:     ccan/ccan/tal/tal.c:517 (tal_alloc_arr_)
lightningd-5 2024-11-28T05:02:27.586Z **BROKEN** lightningd:     ccan/ccan/tal/tal.c:861 (tal_dup_)
lightningd-5 2024-11-28T05:02:27.586Z **BROKEN** lightningd:     common/utils.c:150 (utf8_str)
lightningd-5 2024-11-28T05:02:27.589Z **BROKEN** lightningd:     lightningd/datastore.c:23 (json_add_datastore)
lightningd-5 2024-11-28T05:02:27.589Z **BROKEN** lightningd:     lightningd/datastore.c:205 (json_datastore)
lightningd-5 2024-11-28T05:02:27.590Z **BROKEN** lightningd:     lightningd/jsonrpc.c:808 (command_exec)
lightningd-5 2024-11-28T05:02:27.590Z **BROKEN** lightningd:     lightningd/jsonrpc.c:954 (rpc_command_hook_final)
lightningd-5 2024-11-28T05:02:27.590Z **BROKEN** lightningd:     lightningd/plugin_hook.c:196 (plugin_hook_call_next)
lightningd-5 2024-11-28T05:02:27.591Z **BROKEN** lightningd:     lightningd/plugin_hook.c:183 (plugin_hook_callback)
lightningd-5 2024-11-28T05:02:27.593Z **BROKEN** lightningd:     lightningd/plugin.c:663 (plugin_response_handle)
lightningd-5 2024-11-28T05:02:27.593Z **BROKEN** lightningd:     lightningd/plugin.c:775 (plugin_read_json_one)
```

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-12-20 15:36:07 +10:30
Rusty Russell
5c53ed73fb CI: disable --force-flaky.
This should help us fix the flakes.  Dealing with them was a major
headache at the end of the last release (and they covered up real bugs!).

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-12-20 15:36:07 +10:30
Rusty Russell
fa10323847 Changelog: update to match 24.11.1 branch now that's released.
Changelog-None: changelog updated.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-12-19 10:52:35 +10:30
Rusty Russell
2c8d9d0deb pytest: actually test xpay/pay return similarity.
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-12-18 14:04:14 +10:30
Rusty Russell
d7adf06dfe xpay: created_at response from pay compatibility is a number, not integer.
Reported-by: @hMsats
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-12-18 14:04:14 +10:30
Rusty Russell
3e9a4fc750 xpay: simplify printing of destination.
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-12-18 14:04:14 +10:30
Lagrang3
545220dfbc xpay: add destination to output
Changelog-Add: xpay: add destination to xpay success output when xpay-handle-pay is active.

Signed-off-by: Lagrang3 <lagrang3@protonmail.com>
2024-12-18 14:04:14 +10:30
Rusty Russell
84f30b12f7 pytest: bonus test to make sure xpay uses zeroconf channels correctly.
It needs to use the channel alias here, and it does.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-12-17 15:59:30 +10:30
Rusty Russell
a2f58a28ba lightningd: injectpaymentonion can use scids of unannounced channels.
Cut & paste from the forwarding code, where we don't let onions use the
unannounced scids.  Obviously local commands can use them.

Reported-by: @michael1011
Changelog-Fixed: JSON-RPC: xpay now works through unannounced channels.
2024-12-17 15:59:30 +10:30
Rusty Russell
92c45712d2 pytest: test xpay using unannounced channels.
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-12-17 15:59:30 +10:30
Rusty Russell
d26ea6673d xpay: more accurately reflect pay when xpay-handle-pay is set.
Note that the slight code reorder changes the JSON order, which is generally
undefined, but our doc checker is very strict!

Changelog-Changed: `xpay` now gives the same JSON success return as documented by `pay` when `xpay-handle-pay` is set.
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
Fixes: https://github.com/ElementsProject/lightning/issues/7923
2024-12-17 15:49:03 +10:30
Rusty Russell
428c76068c xpay: emulate maxfeepercent and exemptfee when xpay-handle-pay used
maxfeepercent is use by Zeus, so let's make that work.

maxfee is more precise, so it's the only xpay option (maxfee was added
to pay later).

[ Fix to ppm logic by Lagrang3, thanks! --RR ]

Fixes: https://github.com/ElementsProject/lightning/issues/7926
Changelog-Changed: JSON-RPC: With `xpay-handle-pay` set, xpay will now be used even if `pay` uses maxfeeprecent or exemptfee parameters (e.g. Zeus)
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-12-17 10:54:31 +10:30
Rusty Russell
cf22762c8f xpay: tell injectpaymentonion what the amount being delivered to destination is.
This means that it gets shown in listsendpays: omitting this broke spark, apparently!

Changelog-Changed: `xpay` now populates more fields, so `listsendpays` and `listpays` show `destination` and `amount_msat` fields for xpay payments.
Fixes: https://github.com/ElementsProject/lightning/issues/7881
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-12-17 08:14:45 +10:30
Rusty Russell
8202929a00 lightningd: populate listsendpays destination from injectpaymentonion if we can.
If they give us the invstring, we can at least set who signed the invoice.  Of course,
it might not be a real node_id (with blinded paths).

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-12-17 08:14:45 +10:30
Rusty Russell
80c43ec97d injectpaymentionion: allow specification of actual amount which reaches destination.
This appears in listsendpays / listpays, and is useful information (if we know!).

This doesn't fix old payments, but means that xpay can use this for new payments.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-12-17 08:14:45 +10:30
Rusty Russell
aaca16d313 doc: fix injectpaymentonion schema.
I used an unknown arg and it didn't complain.  injectpaymentonion's schema predated
the sweep which fixed up use of "additionalProperties".

Indeed, we were missing some properties!

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-12-17 08:14:45 +10:30
Lagrang3
7be96ae8bc lightning-cli: fix malformed response bug
There was a wrong assumption that the number of bytes read
by `cli_read` would get us for each correctly read token
two extra CR characters. As a matter of fact one could read
enough characters to parse the first token, but the two
extra CR characters are not guaranteed.

```
==143570== Memcheck, a memory error detector
==143570== Copyright (C) 2002-2022, and GNU GPL'd, by Julian Seward et al.
==143570== Using Valgrind-3.19.0 and LibVEX; rerun with -h for copyright info
==143570== Command: /home/lagrange/BACKUP/l4-appdata/github/lagrang3/lightning/cli/lightning-cli --lightning-dir=/tmp/askrene_benchmark/lightning -k getroutes source=032ed0d87ba2bd68e3a386717cf2faaae4fa6d6da247986b1997113930e4f841d5 destination=03b2f16bf472dd03c55c2ce9910aab717321db4489cd87df5225adadb08031da4b amount_msat=100000sat final_cltv=6 layers=[] maxfee_msat=500sat
==143570==
==143570== Invalid read of size 1
==143570==    at 0x484A430: memmove (vg_replace_strmem.c:1382)
==143570==    by 0x10C3D2: main (lightning-cli.c:871)
==143570==  Address 0x4a62f80 is 0 bytes after a block of size 1,040 alloc'd
==143570==    at 0x48407B4: malloc (vg_replace_malloc.c:381)
==143570==    by 0x11402E: allocate (tal.c:256)
==143570==    by 0x11471E: tal_alloc_ (tal.c:473)
==143570==    by 0x1147EA: tal_alloc_arr_ (tal.c:517)
==143570==    by 0x10C206: main (lightning-cli.c:816)
==143570==
==143570== Invalid read of size 1
==143570==    at 0x484A43D: memmove (vg_replace_strmem.c:1382)
==143570==    by 0x10C3D2: main (lightning-cli.c:871)
==143570==  Address 0x4a62f81 is 1 bytes after a block of size 1,040 alloc'd
==143570==    at 0x48407B4: malloc (vg_replace_malloc.c:381)
==143570==    by 0x11402E: allocate (tal.c:256)
==143570==    by 0x11471E: tal_alloc_ (tal.c:473)
==143570==    by 0x1147EA: tal_alloc_arr_ (tal.c:517)
==143570==    by 0x10C206: main (lightning-cli.c:816)
==143570==
==143570== Invalid write of size 1
==143570==    at 0x484A433: memmove (vg_replace_strmem.c:1382)
==143570==    by 0x10C3D2: main (lightning-cli.c:871)
==143570==  Address 0x4a62f80 is 0 bytes after a block of size 1,040 alloc'd
==143570==    at 0x48407B4: malloc (vg_replace_malloc.c:381)
==143570==    by 0x11402E: allocate (tal.c:256)
==143570==    by 0x11471E: tal_alloc_ (tal.c:473)
==143570==    by 0x1147EA: tal_alloc_arr_ (tal.c:517)
==143570==    by 0x10C206: main (lightning-cli.c:816)
```

Changelog-Fixed: lightning-cli: fix "malformed response" bug

Signed-off-by: Lagrang3 <lagrang3@protonmail.com>
2024-12-16 10:36:32 +10:30
Rusty Russell
73415d35c9 common: don't send trace messages by default, don't ratelimit at all.
We ratelimited DEBUG messages, but that can be annoying and cause us to miss things.
We demoted the worst offenders in the last release, to TRACE level.

Now, only log trace if it's wanted, and never suppress DEBUG.

Changelog-Changed: Logging: we no longer suppress DEBUG messages from subdaemons.
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
Fixes: https://github.com/ElementsProject/lightning/issues/7917
2024-12-16 09:48:51 +10:30
Lakshya Singh
7703cf7fec splice: alpine build warning causing failure
header sys/errno.h gets re-directed to errno.h leading to warning and
then failure so instead directly referencing the header

Changelog-None: change header

Signed-off-by: Lakshya Singh <lakshay.singh1108@gmail.com>
2024-12-16 09:36:17 +10:30
Marcel Hernandez
d6bd61157e Changelog-Fixed: xpay no longer logs "Got command" at info level. 2024-12-15 21:53:43 +10:30
daywalker90
dcb6f2cb2e rust: bump versions for 24.11 release
Changelog-None
2024-12-10 09:37:30 +01:00
Rusty Russell
cb1bd82c86 Final changes for v24.11
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-12-09 14:54:50 +10:30
Rusty Russell
8547cc15c8 doc: fix final release make line.
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-12-09 14:54:50 +10:30
Rusty Russell
cc07f9afc6 v24.11rc4: hopefully the final Release Candidate
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-12-06 15:35:11 +10:30
Christian Decker
1adbd70678 logs: Correct an sign mismatch printing the depth change
We are checking if `txw->depth` is `-1` and then print it, when we
clearly want `depth` instead.

Changelog-Fixed logs: When printing depths some unsigned numbers could overflow
2024-12-06 15:12:51 +10:30
Rusty Russell
f0c5ea2e1e doc: document and test the onionmessage_forward_fail notification.
Doing exactly what we expect to do: initiate a connection and then
forward the message.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-12-05 17:38:16 +10:30
Rusty Russell
e655f69b73 lightningd: notification for onionmessage_forward_fail.
Changelog-Added: Plugins: new notification `onionmessage_forward_fail`.
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-12-05 17:38:16 +10:30
Rusty Russell
8e4b589a9e connectd: message to tell lightningd if we couldn't forward an onion message.
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-12-05 17:38:16 +10:30
Rusty Russell
d196b9bb53 doc: document (and test) the injectonionmessage API.
It's actually tested by fetchinvoice, but doing an explicit test in Python
allows for schema checking!

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
Changelog-Changed: JSON-RPC: `injectonionmessage` API simplified and documented.
2024-12-05 17:38:16 +10:30
Rusty Russell
57b199bb16 lightningd: simplify injectonionmessage API.
It's undocumented and only used in one place, so we can change it (it
was new in 24.08).

We really want to be able to just handle a raw onionmessage: this allows
oblivious sending of messages, but also, in combination with the coming
onionmessage_forward_fail notification, allows us to connect then
reinject.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-12-05 17:38:16 +10:30
fanquake
e00e7053fd doc: minor changes to repro.md
Clarify that the ability to reproducibly build a piece of software has
nothing to do with being a maintainer.

Minor typo/grammar fixes.

Changelog-None.
2024-12-05 13:12:39 +10:30
fanquake
ff471679b9 doc: remove use of sudo from repro.md
`sudo` is not required to complete the steps outlined here.

Changelog-None.
2024-12-05 13:12:39 +10:30
Rusty Russell
b520543867 gossipd: log at trace, not debug for regular messages.
See: https://github.com/ElementsProject/lightning/issues/7899

A node with 23 connections gets far too many debug messages.

Changelog-Fixed: `gossipd` now does logging at trace, not debug level.
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-12-05 11:43:50 +10:30
ShahanaFarooqui
2791c60bb2 ci: Removed branch testing due to checkout confusion between branch vs tag
- Removed branch testing as it is not required. Point releases will trigger the event due to `tag` push even when it is not from master branch.

- Added version in inputs for testing

- Added missing `inputs` tag

Changelog-None.
2024-12-03 21:32:22 +10:30
Rusty Russell
f2b4b507fb CHANGELOG: update for rc3.
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
Changelog-None: The changelog itself was changed.
2024-12-03 12:25:28 +10:30
Se7enZ
42d43b2708 build: Prepare release draft in Github actions. 2024-12-03 11:56:23 +10:30
Se7enZ
1f31aa73fa build: Sign aggregate release artifact from Github. 2024-12-03 11:56:23 +10:30
Se7enZ
79273220f4 build: Add architecture to Ubuntu repro artifacts ([#6228]).
Changelog-Changed: Added architecture identifier to Ubuntu release
artifacts. ([#6228])
2024-12-03 11:56:23 +10:30
Se7enZ
f2716092be build: Remove unused Dockerfiles, scripts and Github action. 2024-12-03 11:56:23 +10:30
Se7enZ
659d607fc4 doc: Update release checklist for CI build. 2024-12-03 11:56:23 +10:30
Se7enZ
f789f9cb21 build: Allow for signing releases without building a zip.
Adds a `--without-zip` parameter default `false` which optionally
skips the archive, to allow for signing releases from CI.
2024-12-03 11:56:23 +10:30
Se7enZ
b9b81c6918 build: Matrix strategy for release builds ([#7776]).
Also modifies the `build-release.sh` script to optionally
accept specific distribution targets for Ubuntu releases.
2024-12-03 11:56:23 +10:30
Se7enZ
c99b72da1c build: Release build automation ([#7776]).
Changelog-None
2024-12-03 11:56:23 +10:30
Rusty Russell
b5d1acee45 wire: call unknown types "UNKNOWN X" not "INVALID X".
It's freaking people out when they see things like:

```
 2024-11-11T05:26:41.281Z DEBUG ...53c-connectd: peer_out INVALID 22859
```

Fixes: https://github.com/ElementsProject/lightning/issues/7802
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
Changelog-Changed: connectd: log unknown messages as "UNKNOWN" not "INVALID" to avoid freaking people out.
2024-12-02 15:09:45 +10:30
Rusty Russell
113156858b xpay: don't excees maxfee *overall*.
We were handing "maxfee" to every getroutes call, even if we had already
used some of the fees.

Reported-by: @daywalker90
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
Changelog-None: xpay is new this release.
2024-12-02 14:31:11 +10:30
Rusty Russell
d0b470618e pytest: test for maxfee compliance.
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-12-02 14:31:11 +10:30
ShahanaFarooqui
06d7971813 doc: Update info on 'cl-repro' script
Changelog-None.
2024-11-30 14:38:27 +01:00
Rusty Russell
b8e5b122d2 decode: don't fail to decode just because a bolt12 invoice has expired.
In fact, there are several places where we try to decode old invoices,
and they should all work.  The only place we should enforce expiration is
when we're going to pay.

This also revealed that xpay wasn't checking bolt11 expiries!

Reported-by: hMsats
Fixes: https://github.com/ElementsProject/lightning/issues/7869
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
Changelog-Fixed: JSON-RPC: `decode` refused to decode expired bolt12 invoices.
2024-11-30 13:17:55 +01:00
Rusty Russell
14cb0574f7 pytest: test (fails) for decoding expired bolt12 invoices.
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-11-30 13:17:55 +01:00
Rusty Russell
996fff94fd plugins/Makefile: make cln-grpc depend on ALL THE THINGS.
```
error[E0277]: the trait bound `cln_rpc::model::requests::AskrenereserveRequest: From<pb::AskrenereserveRequest>` is not satisfied
    --> cln-grpc/src/server.rs:3994:56
     |
3994 |         let req: requests::AskrenereserveRequest = req.into();
     |                                                        ^^^^ the trait `From<pb::AskrenereserveRequest>` is not implemented for `cln_rpc::model::requests::AskrenereserveRequest`, which is required by `pb::AskrenereserveRequest: Into<_>`
     |
     = note: required for `pb::AskrenereserveRequest` to implement `Into<cln_rpc::model::requests::AskrenereserveRequest>`

error[E0277]: the trait bound `cln_rpc::model::requests::AskreneageRequest: From<pb::AskreneageRequest>` is not satisfied
    --> cln-grpc/src/server.rs:4026:52
     |
4026 |         let req: requests::AskreneageRequest = req.into();
     |                                                    ^^^^ the trait `From<pb::AskreneageRequest>` is not implemented for `cln_rpc::model::requests::AskreneageRequest`, which is required by `pb::AskreneageRequest: Into<_>`
     |
     = note: required for `pb::AskreneageRequest` to implement `Into<cln_rpc::model::requests::AskreneageRequest>`

error[E0277]: the trait bound `cln_rpc::model::requests::GetroutesRequest: From<pb::GetroutesRequest>` is not satisfied
    --> cln-grpc/src/server.rs:4058:51
     |
4058 |         let req: requests::GetroutesRequest = req.into();
     |                                                   ^^^^ the trait `From<pb::GetroutesRequest>` is not implemented for `cln_rpc::model::requests::GetroutesRequest`, which is required by `pb::GetroutesRequest: Into<_>`
     |
     = note: required for `pb::GetroutesRequest` to implement `Into<cln_rpc::model::requests::GetroutesRequest>`

error[E0277]: the trait bound `cln_rpc::model::requests::AskrenedisablenodeRequest: From<pb::AskrenedisablenodeRequest>` is not satisfied
    --> cln-grpc/src/server.rs:4090:60
     |
4090 |         let req: requests::AskrenedisablenodeRequest = req.into();
     |                                                            ^^^^ the trait `From<pb::AskrenedisablenodeRequest>` is not implemented for `cln_rpc::model::requests::AskrenedisablenodeRequest`, which is required by `pb::AskrenedisablenodeRequest: Into<_>`
     |
     = note: required for `pb::AskrenedisablenodeRequest` to implement `Into<cln_rpc::model::requests::AskrenedisablenodeRequest>`

error[E0277]: the trait bound `cln_rpc::model::requests::AskreneinformchannelRequest: From<pb::AskreneinformchannelRequest>` is not satisfied
    --> cln-grpc/src/server.rs:4122:62
     |
4122 |         let req: requests::AskreneinformchannelRequest = req.into();
     |                                                              ^^^^ the trait `From<pb::AskreneinformchannelRequest>` is not implemented for `cln_rpc::model::requests::AskreneinformchannelRequest`, which is required by `pb::AskreneinformchannelRequest: Into<_>`
     |
     = note: required for `pb::AskreneinformchannelRequest` to implement `Into<cln_rpc::model::requests::AskreneinformchannelRequest>`

error[E0277]: the trait bound `cln_rpc::model::requests::AskrenecreatechannelRequest: From<pb::AskrenecreatechannelRequest>` is not satisfied
    --> cln-grpc/src/server.rs:4154:62
     |
4154 |         let req: requests::AskrenecreatechannelRequest = req.into();
     |                                                              ^^^^ the trait `From<pb::AskrenecreatechannelRequest>` is not implemented for `cln_rpc::model::requests::AskrenecreatechannelRequest`, which is required by `pb::AskrenecreatechannelRequest: Into<_>`
     |
     = note: required for `pb::AskrenecreatechannelRequest` to implement `Into<cln_rpc::model::requests::AskrenecreatechannelRequest>`

error[E0277]: the trait bound `cln_rpc::model::requests::AskreneupdatechannelRequest: From<pb::AskreneupdatechannelRequest>` is not satisfied
    --> cln-grpc/src/server.rs:4186:62
     |
4186 |         let req: requests::AskreneupdatechannelRequest = req.into();
     |                                                              ^^^^ the trait `From<pb::AskreneupdatechannelRequest>` is not implemented for `cln_rpc::model::requests::AskreneupdatechannelRequest`, which is required by `pb::AskreneupdatechannelRequest: Into<_>`
     |
     = note: required for `pb::AskreneupdatechannelRequest` to implement `Into<cln_rpc::model::requests::AskreneupdatechannelRequest>`

error[E0277]: the trait bound `cln_rpc::model::requests::AskrenebiaschannelRequest: From<pb::AskrenebiaschannelRequest>` is not satisfied
    --> cln-grpc/src/server.rs:4218:60
     |
4218 |         let req: requests::AskrenebiaschannelRequest = req.into();
     |                                                            ^^^^ the trait `From<pb::AskrenebiaschannelRequest>` is not implemented for `cln_rpc::model::requests::AskrenebiaschannelRequest`, which is required by `pb::AskrenebiaschannelRequest: Into<_>`
     |
     = note: required for `pb::AskrenebiaschannelRequest` to implement `Into<cln_rpc::model::requests::AskrenebiaschannelRequest>`

error[E0277]: the trait bound `cln_rpc::model::requests::AskrenelistreservationsRequest: From<pb::AskrenelistreservationsRequest>` is not satisfied
    --> cln-grpc/src/server.rs:4250:65
     |
4250 |         let req: requests::AskrenelistreservationsRequest = req.into();
     |                                                                 ^^^^ the trait `From<pb::AskrenelistreservationsRequest>` is not implemented for `cln_rpc::model::requests::AskrenelistreservationsRequest`, which is required by `pb::AskrenelistreservationsRequest: Into<_>`
     |
     = note: required for `pb::AskrenelistreservationsRequest` to implement `Into<cln_rpc::model::requests::AskrenelistreservationsRequest>`

error[E0277]: the trait bound `cln_rpc::model::requests::InjectpaymentonionRequest: From<pb::InjectpaymentonionRequest>` is not satisfied
    --> cln-grpc/src/server.rs:4282:60
     |
4282 |         let req: requests::InjectpaymentonionRequest = req.into();
     |                                                            ^^^^ the trait `From<pb::InjectpaymentonionRequest>` is not implemented for `cln_rpc::model::requests::InjectpaymentonionRequest`, which is required by `pb::InjectpaymentonionRequest: Into<_>`
     |
     = note: required for `pb::InjectpaymentonionRequest` to implement `Into<cln_rpc::model::requests::InjectpaymentonionRequest>`

error[E0277]: the trait bound `cln_rpc::model::requests::XpayRequest: From<pb::XpayRequest>` is not satisfied
    --> cln-grpc/src/server.rs:4314:46
     |
4314 |         let req: requests::XpayRequest = req.into();
     |                                              ^^^^ the trait `From<pb::XpayRequest>` is not implemented for `cln_rpc::model::requests::XpayRequest`, which is required by `pb::XpayRequest: Into<_>`
     |
     = note: required for `pb::XpayRequest` to implement `Into<cln_rpc::model::requests::XpayRequest>`
```

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-11-29 09:46:17 +10:30
Rusty Russell
b9cd30bde8 CHANGELOG: update for rc2.
Somehow it was doubled up, so fixed.

Several crashes fixed.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-11-29 09:46:17 +10:30
Alex Myers
bb30049eca gossipd: seeker: try to autoconnect with no peers
Testing autoconnect in --offline mode, the autoconnect never functions
if the seeker has not gotten out of the startup state.  This commit
overloads the  counter to start the autoconnect
attempt on the second round through the seeker_check.

Changelog-None
2024-11-28 19:02:35 +10:30
Alex Myers
b9984f876c lightningd: disable seeker autoconnect when --offline
Changelog-None
2024-11-28 19:02:35 +10:30
daywalker90
2ba05ef2b8 msggen: add missing rpc commands new to 24.11
Changelog-None
2024-11-28 17:39:26 +10:30
daywalker90
703c11515d msggen: add support for short_channel_id_dir and pubkey
Changelog-None
2024-11-28 17:39:26 +10:30
Rusty Russell
2e90f59dfe connectd: fix crash when we get an incoming conn while outgoing attempt is ratelimited.
```
Program received signal SIGSEGV, Segmentation fault.
0x000000001014e9d8 in io_set_finish_ (conn=0x0, finish=0x0, arg=0x0) at ccan/ccan/io/io.c:137
137             conn->finish = finish;
(gdb) bt
    incoming=true) at connectd/connectd.c:394
```

Fixes: #7871
Reported-by: grubles
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
Changelog-None: broken in this release
2024-11-28 17:24:47 +10:30
daywalker90
36ad654fc1 Makefile: ensure that cln-grpc depends on msggen generated rust files.
Changelog-None
2024-11-28 16:40:02 +10:30
Rusty Russell
020bd97a5a startup_regtest: fix clnrest detection.
The .py extension gets stripped from the plugin name, so it didn't work.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-11-28 16:37:33 +10:30
Rusty Russell
39fbced71e contrib/startup_regtest: set grpc-port so we can start more than one.
A side-effect of having grpc start by default.  Annoyingly, if it
can't bind it simply exits, with no message, so I had to guess what
was happening.

Reported-by: @daywalker90
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-11-28 16:37:33 +10:30
ShahanaFarooqui
a3a33fe3be doc: Add GENERATE_EXAMPLES env
- Run with environment variable `GENERATE_EXAMPLES`
- Update cln version in getinfo example on `make update-versions`
- Added two `dev` configs, dev-no-plugin-checksum and dev-no-version-checks, to match CI listconfigs
- Changed commando rpc example from `getinfo` to `newaddr` to avoid unneccessary file updates for future builds
- Stabilized `bkpr-editdescriptionbyoutpoint`, `listclosedchannels` and `listaddresses` examples
2024-11-28 15:56:16 +10:30
ShahanaFarooqui
075f180596 doc: Add GENERATE_EXAMPLES details
Changelog-None.
2024-11-28 15:56:16 +10:30
ShahanaFarooqui
0a7956b6d4 ci: Add GENERATE_EXAMPLES env in CI & docker build script 2024-11-28 15:56:16 +10:30
ShahanaFarooqui
b8b4e7c7fd make: add repeat-doc-examples in Makefile for easier future testing 2024-11-28 15:56:16 +10:30
ShahanaFarooqui
9c3bef0da0 make: Added update-doc-examples in update-versions 2024-11-28 15:56:16 +10:30
ShahanaFarooqui
7ff6852073 pyln: Add GENERATE_EXAMPLES environment variable for Testing 2024-11-28 15:56:16 +10:30
Rusty Russell
9499d5c682 gossipd: fix crash in seeker rotation code.
Reported-by: hMsats
Fixes: https://github.com/ElementsProject/lightning/issues/7875
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
Changelog-None: introduced in rc1
2024-11-28 15:56:05 +10:30
Alex Myers
d099f9fe5b connectd: force our own channel gossip to more peers
Large nodes were not always getting their own channel gossip out
reliably.  The number of peers we spam our own channel gossip to
is limited to save large nodes on startup, but this should be
relaxed slightly to ensure propagation.

Changelog-Fixed: Own-channel gossip is broadcast to more peers on connect.
2024-11-28 14:54:08 +10:30
ShahanaFarooqui
11b294d18e doc: pre-build CI fix due to newly tagged version
Changelog-None.
2024-11-28 08:55:18 +10:30
Rusty Russell
034d3c9628 Build: update to version 24.11rc1
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-11-27 06:27:50 +10:30
Rusty Russell
437042057d CHANGELOG: v24.11-rc1
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-11-27 06:27:50 +10:30
ShahanaFarooqui
2e30f96d92 doc: Updated section for Generating Examples in Schema 2024-11-26 21:45:19 +10:30
ShahanaFarooqui
fffafe53eb make: Add check-doc-examples in Makefile for check-source 2024-11-26 21:45:19 +10:30
ShahanaFarooqui
e568d69867 doc: Lock askrene example values 2024-11-26 21:45:19 +10:30
ShahanaFarooqui
9592facf83 doc: Lock example values
Changelog-Added: Test script generates all RPC documentation examples now.
2024-11-26 21:45:19 +10:30
ShahanaFarooqui
01ede70e80 gitignore: cln-xpay plugin 2024-11-26 21:45:19 +10:30
Rusty Russell
fba738b65e askrene: really fix race between layer creation and persistent layer loading.
Using jsonrpc_request_sync, layers are loaded before we finish init,
so we never can be asked to create a layer before we've loaded it
(xpay creates a layer immediately on startup).

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
Changelog-None: persistent layers new this release.
2024-11-26 16:04:13 +10:30
Rusty Russell
d256e11108 askrene: reorder functions.
No code changes.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-11-26 16:04:13 +10:30
Rusty Russell
af629e600e askrene: don't re-save layers as we restore them!
Create lower-level versions of routines to create biases, layers,
constraints, etc and only save the ones called from the public APIs.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
Changelog-None: persistent layers were only added in this release
2024-11-26 16:04:13 +10:30
Rusty Russell
efacada7dd spender: fix multifundchannel ids.
They're not always 34 (aka '"').  This is a side-effect of ids
changing from u64 to strings quite a while ago.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-11-26 16:04:13 +10:30
Rusty Russell
20257c3308 lightningd: --dev-low-prio-anchor-blocks and test for low-priority anchors.
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-11-26 14:49:36 +10:30
Rusty Russell
de30f9c4b2 anchors: create low priority anchor to spend commit tx within a week.
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
Changelog-Changed: Protocol: we now create a low-priority (2016 down to 12 blocks fee target) anchor for low-fee unilateral closes even if there's no urgency.
2024-11-26 14:49:36 +10:30
Rusty Russell
737ae8e1eb lightningd: separate routine to gather utxos and create anchor.
We're going to call this twice.  But this patch also takes care
that a failed attempt to create an anchor doesn't alter other
variables!

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-11-26 14:49:36 +10:30
Rusty Russell
0332babdb9 lightningd: minor anchorspend cleanups.
1. merge_deadlines can't really fail.
2. We don't care about incoming HTLCs with no preimage.
3. Debug print anchor points as soon as we calc them.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-11-26 14:49:36 +10:30
Rusty Russell
1cbc96f0d9 lightningd: remember when we started closing channel.
This lets us maintain a reasonable 2 week target for commitment tx.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-11-26 14:49:36 +10:30
Christian Decker
7b18030ee2 grpc: Do not print wildcard notifications that don't have a handler
Changelog-Fixed: grpc: We no longer log a warning if a notification does not have a handler
2024-11-25 15:41:43 +01:00
niftynei
46fde419b1 pytest: fix up coin_move tests now anchors don't get redundantly spent/ 2024-11-25 20:23:21 +10:30
Rusty Russell
5192eebef9 lightningd: wire channel closing tx through channel_fail_permanent.
Cleans up the API: we have two functions now, one which is explicitly for
"I'm failing this because I saw this tx onchain".

Now we can correctly report the tx which closed the channel (previously
we would always report our own tx(s)!).

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
Changelog-Fixed: JSON-RPC: `close` now correctly reports the txid of the remote onchain unilateral tx if it races with a peer close.
Changelog-Fixed: Protocol: we no longer try to spend anchors if a commitment tx is already mined (reported by @niftynei).
Fixes: #7526
2024-11-25 20:23:21 +10:30
Rusty Russell
bfb94fe0c3 lightnind: make channel_set_state string arg const.
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-11-25 20:23:21 +10:30
Rusty Russell
656ac34756 lightningd: make close_txs parameter to resolve_close_command const.
We don't need to change these txs.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-11-25 20:23:21 +10:30
niftynei
193b4425ab nit: spelling fix 2024-11-25 20:23:21 +10:30
Rusty Russell
5701123209 pytest: fix flake in test_gossip_force_broadcast_channel_msgs
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-11-25 15:39:13 +10:30
Rusty Russell
7cdf45bb00 pytest: fix flake in test_ping_timeout
The seeker can send a full gossip query, which means the ping doesn't happen
(it needs 14-45 seconds of quiet!).

We disable the gossip_queries feature, so it doesn't ask.

```
    def test_ping_timeout(node_factory):
        # Disconnects after this, but doesn't know it.
        l1_disconnects = ['xWIRE_PING']
    
        l1, l2 = node_factory.get_nodes(2, opts=[{'dev-no-reconnect': None,
                                                  'disconnect': l1_disconnects},
                                                 {'dev-no-ping-timer': None}])
        l1.rpc.connect(l2.info['id'], 'localhost', l2.port)
    
        # This can take 10 seconds (dev-fast-gossip means timer fires every 5 seconds)
        l1.daemon.wait_for_log('seeker: startup peer finished', timeout=15)
        # Ping timers runs at 15-45 seconds, *but* only fires if also 60 seconds
        # after previous traffic.
>       l1.daemon.wait_for_log('dev_disconnect: xWIRE_PING', timeout=60 + 45 + 5)

tests/test_connection.py:4194: 
...
>                   raise TimeoutError('Unable to find "{}" in logs.'.format(exs))
E                   TimeoutError: Unable to find "[re.compile('dev_disconnect: xWIRE_PING')]" in logs.
```

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-11-25 15:39:13 +10:30
Rusty Russell
faf7ae6ad4 pytest: add test for connection ratelimiting.
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-11-25 15:39:13 +10:30
Rusty Russell
3d294f813d connectd: limit to 10 connections at once.
We wait until a connection fails, or a subd is connected to the peer,
before letting another one through.  This should prevent us from
overwhelming lightningd on large nodes, but unlike the previous back-off,
it's based on how fast lightningd is, not an arbitrary time.

We also let one through each second, in case we're connecting to many,
but not doing anything but gossip (e.g. 100 explicit connect
commands).

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
Changelog-Changed: Reconnecting to peers at startup should be significantly faster (dependent on machine speed).
2024-11-25 15:39:13 +10:30
Rusty Russell
3587afeaa2 connectd: remove transient flag.
The important flag replaces it, and now we can be more intelligent about
eviction in overload.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-11-25 15:39:13 +10:30
Rusty Russell
73b9812178 pytest: restore test_sendpay_grouping test.
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-11-25 15:39:13 +10:30
Rusty Russell
15950bb7d4 connectd: reconnect for non-transient connections.
Rather than have lightningd call us repeatedly to try to connect, have
it tell us what peers are transient and aren't, and connectd will
automatically try to maintain that connection.

There's a new "downgrade_peer" message to tell it a peer is now
transient: to make it non-transient we simply tell connectd to
connect as a non-transient.

The first time, I missed that dual_open_control does its own state
transitions :(

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
Changelog-Changed: `connectd` now handles maintaining/reconnecting to important peers, and we remember the last successful address we connected to.
2024-11-25 15:39:13 +10:30
Rusty Russell
ff290b19c9 recovery: save last_known_addr for peer if we know it.
This is more useful than the last address, which may be it connecting
to us.  And use it when we restore it.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-11-25 15:39:13 +10:30
Rusty Russell
22a481fbaa common: routine to make wireaddr_internal from wireaddr.
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-11-25 15:39:13 +10:30
Rusty Russell
68feb55dbf wallet: save last known address.
If we connected out, remember that address.  We always remember the last
address, but that may be an incoming address.  This is explicitly the last
outgoing address which worked.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-11-25 15:39:13 +10:30
Rusty Russell
64af5db45c lightningd: generalize peer_any_channel to filter on entire channel, not just state.
We're going to use this to ask if there are any channels which make it
important to reconnect to the peer.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-11-25 15:39:13 +10:30
Rusty Russell
4ee59e7a49 connectd: expose --dev-no-reconnect and --dev-fast-reconnect options.
Once connectd is controlling reconnections, it'll need these.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-11-25 15:39:13 +10:30
Rusty Russell
c6fce50951 gossipd: don't tell connectd what address to connect to.
In fact, only 951 of 17419 (5%) of node announcements are missing an address
(and gossipd doesn't know if we can connect to Tor addresses anyway) so
just check it *has* a node_announcement.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-11-25 15:39:13 +10:30
Rusty Russell
23dc10cf81 connectd: get our own addresses to contact node from node_announcements.
Let lightningd feed us hints to try first, but we can extract the
addresses from node_announcement messages ourselves.

(Lightningd used to ask gossipd on our behalf: this is far simpler!)

One side effect of this is that we don't hand back address hints given to us
by lightningd: it would use these again for reconnecting.  This is breaks
test_sendpay_grouping, so we disable it temporarily.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-11-25 15:39:13 +10:30
Rusty Russell
5b92383b02 connectd: send self-advertizing gossip rather than having gossipd do it.
It's now trivial for us to do this ourselves, since we have gossmap.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-11-25 15:39:13 +10:30
Alex Myers
11580dfd43 pyln-testing: disable seeker autoconnect by default
This avoids test flakes, but can be explicitly set if needed.

Changelog-None
2024-11-24 12:03:16 +10:30
Christian Decker
c596550de1 common: Make trace debugging output configurate at compile time
Just added a couple of compile-time guards and sprinkled the invariant
checking in a couple of places (disabled if compile time guard is
unset).
2024-11-24 10:24:31 +10:30
Christian Decker
557142627f common: Fix a potential cycle in the trace structure
It turns out that under some circumstances we end up clearing the
pointee of `current` but not the pointer. Thus when we select the next
slot we can end up reusing the same slot, making it its own parent.

We forcefull break these cycles by enforcing that `current` should
never be returned and be set as its own parent.

Changelog-None
2024-11-24 10:24:31 +10:30
Christian Decker
a6c81d4174 common: Add a tree checker for trace spans
Trace spans form a tree, but we don't actually check that the
structure doesn't break. Breakage can for example come if we use the
same key accidentally, making a new span its own ancestor.
2024-11-24 10:24:31 +10:30
Christian Decker
2e59ab8f15 common: Remove the recursive parent resolution in traces
We have the space in memory set aside anyway, so let's just copy the
`trace_id` into the span itself, rather than resolving the `root` at
time of emission.
2024-11-24 10:24:31 +10:30
Christian Decker
57b9648d30 common: Resume the startup trace after exiting io_loop
This was a bit harder to identify: during an `io_loop` run we suspend
the current span before handing over to `io_loop`, and later when a callback
is called we resume the span again. Depending on how we return from
the `io_loop` instance that is used to drive the startup, we either
have resumed the last span, or we don't. Since we start a span before
`io_loop` and want it to be emitted afterwards, we need to take care
of the case where we returned from a callback that did not resume, and
therefore the current context is empty.

Making `trace_span_resume` idempotent means we can just resume it
manually.

Ideally we'd push the suspend / resume logic down into `io_loop`
itself, and then we'd have just one place. Maybe suspend and resume
callbacks that can be configured in `io_loop`?
2024-11-24 10:24:31 +10:30
Christian Decker
1900dd53bf db: Fix a broken span context pointer 2024-11-24 10:24:31 +10:30
Christian Decker
4f3ea8c048 common: Add some debuggig capabilities to the trace subsystem
After adding the DB query instrumentation we ran into a couple of
issues, with spans not being resumed correctly, and it was rather hard
to identify the problem. This adds debug statements so we can trace
the tracing (traception if you will).

Changelog-None
2024-11-24 10:24:31 +10:30
Matt Whitlock
7a2006842f lightningd/test/Makefile: add missing dependency on header_versions_gen.h
lightningd/test/run-find_my_abspath.c includes ../lightningd.c, which includes
header_versions_gen.h, a generated header file.

lightningd/Makefile correctly declares that lightningd/lightningd.o depends on
header_versions_gen.h, but lightningd/test/Makefile lacks any such declaration
regarding lightningd/test/run-find_my_abspath.c, which leads to build failure:

In file included from lightningd/test/run-find_my_abspath.c:5:
lightningd/test/../lightningd.c:64:10: fatal error: header_versions_gen.h: No such file or directory
   64 | #include <header_versions_gen.h>
      |          ^~~~~~~~~~~~~~~~~~~~~~~

Declare the missing dependency in lightningd/test/Makefile so that Make will
ensure that header_versions_gen.h is generated before it attempts to build
lightningd/test/run-find_my_abspath.o.

Changelog-None
2024-11-23 13:03:00 +01:00
daywalker90
54e7ac6872 startup_regtest: remove experimental-offers flag
Changelog-None
2024-11-23 10:48:32 +10:30
Michael Cho
94c5695d6f Makefile: fix defines on ARM macOS
Due to Darwin-arm64 conditional setting of `CPPFLAGS`, the subsequent
`CPPFLAGS +=` is resolved earlier on ARM macOS which results in empty
paths being used.

Changelog-None
2024-11-23 10:47:32 +10:30
Rusty Russell
dba9746d21 pytest: fix flake in test_gossip_pruning.
If the first one doesn't use the entire timeout, the second might need longer
(I used TIMEOUT=10 normally):

```
FAILED tests/test_gossip.py::test_gossip_pruning - TimeoutError: Unable to find "[re.compile('Pruning channel 103x1x0 from network view')]" in logs.
```

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-11-23 10:20:30 +10:30
Rusty Russell
90ab9325a1 xpay: give an additional block "slack" for CLTV values.
pay does this, xpay does not.  Which means if a block comes in (or you're behind),
you get gratuitous failures:

```
    def test_xpay_simple(node_factory):
        l1, l2, l3, l4 = node_factory.get_nodes(4, opts={'may_reconnect': True})
        node_factory.join_nodes([l1, l2, l3], wait_for_announce=True)
        node_factory.join_nodes([l3, l4], announce_channels=False)

        # BOLT 11, direct peer
        b11 = l2.rpc.invoice('10000msat', 'test_xpay_simple', 'test_xpay_simple bolt11')['bolt11']
>       ret = l1.rpc.xpay(b11)

tests/test_xpay.py:148:
...
        if not isinstance(resp, dict):
            raise TypeError("Malformed response, response is not a dictionary %s." % resp)
        elif "error" in resp:
>           raise RpcError(method, payload, resp['error'])
E           pyln.client.lightning.RpcError: RPC call failed: method: xpay, payload: ('lnbcrt100n1pn5qu7csp53rp0mfwtfsyyy8gzsggepnxgslyalwvz3jkg9ptmqq452ln2nmgqpp58ak9nmfz9l93r0fpm266ewyjrhurhatrs05nda0r03p82cykp0vsdp9w3jhxazl0pcxz72lwd5k6urvv5sxymmvwscnzxqyjw5qcqp99qxpqysgqa798258yppu2tlfj8herr3zuz0zgux79zvtx6z57cmfzs2wdesmr4nvnkcmyssyu6k64ud54eg0v45c3mcw342jj6uy7tu202p6klrcp6ljc9w',), error: {'code': 203, 'message': "Destination said it doesn't know invoice: incorrect_or_unknown_payment_details"}
```

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
Changelog-None: xpay is new this release.
2024-11-23 10:20:30 +10:30
Rusty Russell
4186591a70 pyln-client: restore backwards compatibility with CLN prior to 24.08
24.05 and before requires a "description" field.  We should not have removed it here
until that was EOL!

Changelog-Fixed: pyln-client: plugins now compatible with CLN <= 24.05 (broken in 24.08)
Reported-by: Christian Decker
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-11-22 09:12:27 +01:00
Rusty Russell
d5c0d21db8 gossipd: hand gossmap to gossmap_manage_get_node_addresses, not gossmap_manage.
We don't want to to refresh the gossmap internally: this could invalidate the
gossmap held by the current callers.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-11-22 15:21:45 +10:30
Rusty Russell
69c252e06f gossmap: implement gossmap_random_node(), use it in gossipd.
It's easy for gossmap, since it has access to the htable.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-11-22 15:21:45 +10:30
Alex Myers
363b721cd3 gossipd: use autoconnect-seeker-peers setting 2024-11-22 15:21:45 +10:30
Alex Myers
dc878dc937 lightningd: add option for minimum seeker autoconnect peers
Changelog-added: Added option --autoconnect-seeker-peers, allowing seeker to reach out to new nodes for additional gossip.
2024-11-22 15:21:45 +10:30
Alex Myers
f2243e6013 pytest: Add seeker autoconnect test 2024-11-22 15:21:45 +10:30
Alex Myers
dff5c893e7 gossipd: seeker: select random peer and tell lightningd
This does not validate a node announcement and address, but it
does select a node at random from the gossmap and asks lightningd
to attempt a connection to it.
2024-11-22 15:21:45 +10:30
Alex Myers
7fc214a67f gossipd: add request to connect to new gossip peer
Gossipd uses this to ask lightningd -> connectd to initiate
a connection to a new gossip peer.  This can be used when
there are insufficient peers already connected to gossip with.

Changelog-Changed: Gossipd can now request connections to additional nodes for improved gossip sync
2024-11-22 15:21:45 +10:30
Alex Myers
9cba417ed0 gossipd: seeker: allocate gossiper array at init
This will let us change the default gossipers at runtime
2024-11-22 15:21:45 +10:30
Rusty Russell
9295b4f77e common/test: fix -O3 compile error with gcc-12 (Ubuntu 12.3.0-17ubuntu1) 12.3.0
```
common/test/run-splice_script.c: In function ‘main’:
common/test/run-splice_script.c:349:17: error: ‘%.*s’ directive argument is null [-Werror=format-overflow=]
  349 |         printf("%.*s\n", (int)len, str);
      |                 ^~~~
cc1: all warnings being treated as errors
make: *** [Makefile:297: common/test/run-splice_script.o] Error 1
make: *** Waiting for unfinished jobs....
```

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-11-22 15:21:45 +10:30
Rusty Russell
8566370087 pytest: fix flake in test_gossip_force_broadcast_channel_msgs
We can get more gossip_filter messages now.  And we can also go over max-messages,
so increase that too.

```
        del tally['query_short_channel_ids']
        del tally['query_channel_range']
        del tally['ping']
>       assert tally == {'channel_announce': 1,
                         'channel_update': 3,
                         'node_announce': 1,
                         'gossip_filter': 1}
E       AssertionError: assert {'channel_ann..._announce': 1} == {'channel_ann..._announce': 1}
E         Omitting 2 identical items, use -vv to show
E         Differing items:
E         {'gossip_filter': 2} != {'gossip_filter': 1}
E         {'channel_update': 2} != {'channel_update': 3}
E         Full diff:
E           {
E            'channel_announce': 1,...
E         
E         ...Full output truncated (10 lines hidden), use '-vv' to show

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

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-11-22 14:01:44 +10:30
Rusty Russell
a295099ace pytest: fix flake in test_onchaind_replay.
We actually mine *300* blocks, not 200, and if timing is right l1
can have mined the txid before mine_txid_or_rbf() checks the mempool:

```
    def test_onchaind_replay(node_factory, bitcoind):
        disconnects = ['+WIRE_REVOKE_AND_ACK', 'permfail']
        # Feerates identical so we don't get gratuitous commit to update them
        l1, l2 = node_factory.line_graph(2, opts=[{'watchtime-blocks': 201, 'cltv-delta': 101,
                                                   'disconnect': disconnects,
                                                   'feerates': (7500, 7500, 7500, 7500)},
                                                  {'watchtime-blocks': 201, 'cltv-delta': 101}],
                                         wait_for_announce=True)
    
        inv = l2.rpc.invoice(10**8, 'onchaind_replay', 'desc')
        rhash = inv['payment_hash']
        routestep = {
            'amount_msat': 10**8 - 1,
            'id': l2.info['id'],
            'delay': 101,
            'channel': first_scid(l1, l2)
        }
        l1.rpc.sendpay([routestep], rhash, payment_secret=inv['payment_secret'])
        l1.daemon.wait_for_log('sendrawtx exit 0')
        bitcoind.generate_block(1, wait_for_mempool=1)
    
        # Wait for nodes to notice the failure, this seach needle is after the
        # DB commit so we're sure the tx entries in onchaindtxs have been added
        l1.daemon.wait_for_log("Deleting channel .* due to the funding outpoint being spent")
        l2.daemon.wait_for_log("Deleting channel .* due to the funding outpoint being spent")
    
        # We should at least have the init tx now
        assert len(l1.db_query("SELECT * FROM channeltxs;")) > 0
        assert len(l2.db_query("SELECT * FROM channeltxs;")) > 0
    
        # Generate some blocks so we restart the onchaind from DB (we rescan
        # last_height - 100)
        bitcoind.generate_block(100)
        sync_blockheight(bitcoind, [l1, l2])
    
        # l1 should still have a running onchaind
        assert len(l1.db_query("SELECT * FROM channeltxs;")) > 0
    
        l2.rpc.stop()
        l1.restart()
    
        # Can't wait for it, it's after the "Server started" wait in restart()
        assert l1.daemon.is_in_log(r'Restarting onchaind \(ONCHAIN\): closed in block 109')
    
        # l1 should still notice that the funding was spent and that we should react to it
        _, txid, blocks = l1.wait_for_onchaind_tx('OUR_DELAYED_RETURN_TO_WALLET',
                                                  'OUR_UNILATERAL/DELAYED_OUTPUT_TO_US')
        assert blocks == 200
        bitcoind.generate_block(200)
        # Could be RBF!
>       l1.mine_txid_or_rbf(txid)

tests/test_closing.py:1864: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
contrib/pyln-testing/pyln/testing/utils.py:1375: in mine_txid_or_rbf
    wait_for(lambda: rbf_or_txid_broadcast(txids))
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

success = <function LightningNode.mine_txid_or_rbf.<locals>.<lambda> at 0x7f9b129c4550>
timeout = 180

    def wait_for(success, timeout=TIMEOUT):
        start_time = time.time()
        interval = 0.25
        while not success():
            time_left = start_time + timeout - time.time()
            if time_left <= 0:
>               raise ValueError("Timeout while waiting for {}".format(success))
E               ValueError: Timeout while waiting for <function LightningNode.mine_txid_or_rbf.<locals>.<lambda> at 0x7f9b129c4550>
```

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-11-22 14:01:44 +10:30
Rusty Russell
8132d19ab5 configure: make configuration with address sanitizer find zlib.
The test program has a leak, so address sanitizer complains and makes it
"fail" the zlib detection test!

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-11-22 14:01:44 +10:30
Jesse de Wit
a90d9c9f4f tests: add pay test over unannounced channels
This test fails with cln v24.08.2. Add this test, so it doesn't happen
again.

Changelog-None
2024-11-21 11:22:26 +01:00
Rusty Russell
2c9023ee25 pytest: reenable askrene bias test.
We can fix the median calc by removing the (unused) reverse edges.

Also analyze the failure case in test_real_data: it's a real edge case, so
hardcode that one as "ok".

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-11-21 16:17:52 +10:30
Lagrang3
05514b46e3 Askrene: change median factor to 1.
The ratio of the median of the fees and probability cost is overall not
a bad factor to combine these two features. This is what the
test_real_data shows.

Changelog-None

Signed-off-by: Lagrang3 <lagrang3@protonmail.com>
2024-11-21 16:17:52 +10:30
Lagrang3
2b3fd67dfb askrene: don't skip fee_fallback test
The fee_fallback test would fail after fixing the computation of the
median. Now by we can restore it by making the probability cost factor
1000x higher than the ratio of the median. This shows how hard it is to
combine fee and probability costs and why is the current approach so
fragile.

Changelog-None

Signed-off-by: Lagrang3 <lagrang3@protonmail.com>
2024-11-21 16:17:52 +10:30
Lagrang3
9fdcc26d1d askrene: bugfix queue overflow
Changelog-none

Signed-off-by: Lagrang3 <lagrang3@protonmail.com>
2024-11-21 16:17:52 +10:30
Lagrang3
9966969d4c askrene: remove allocation checks
Rusty: "allocations don't fail"

Signed-off-by: Lagrang3 <lagrang3@protonmail.com>
2024-11-21 16:17:52 +10:30
Lagrang3
460a28bb32 askrene: add compiler flag ASKRENE_UNITTEST
Rusty: "We don't generally use NDEBUG in our code"

Instead use a compile time flag ASKRENE_UNITTEST to make checks on unit
tests that we don't normally need on release code.

Changelog-none

Signed-off-by: Lagrang3 <lagrang3@protonmail.com>
2024-11-21 16:17:52 +10:30
Lagrang3
b1cd26373b askrene: small fixes suggested by Rusty Russell
- use graph_max_num_arcs/nodes instead of tal_count in bound checks,
- don't use ccan/lqueue, use instead a minimalistic queue
  implementation with an array,
- add missing const qualifiers to temporary tal allocators,
- check preconditions with assert,
- remove inline specifier for static functions,

Changelog-None

Signed-off-by: Lagrang3 <lagrang3@protonmail.com>
2024-11-21 16:17:52 +10:30
Lagrang3
44c9609f3a askrene: add arbitrary precision flow unit
Changelog-none: askrene: add arbitrary precision flow unit

Signed-off-by: Lagrang3 <lagrang3@protonmail.com>
2024-11-21 16:17:52 +10:30
Lagrang3
225939a5e3 add ratio ceil and floor operators on amount_msat
Changelog-none: add ratio ceil and floor operators on amount_msat

Signed-off-by: Lagrang3 <lagrang3@protonmail.com>
2024-11-21 16:17:52 +10:30
Lagrang3
4dc1a44cd9 askrene: fix the median
The calculation of the median values of probability and fee cost in the
linear approximation had a bug by counting on non-existing arcs.

Changelog-none: askrene: fix the median

Signed-off-by: Lagrang3 <lagrang3@protonmail.com>
2024-11-21 16:17:52 +10:30
Lagrang3
ee623616d2 askrene: fix CI
check the return value of scanf in askrene unit tests,

Changelog-none: askrene: fix CI

Signed-off-by: Lagrang3 <lagrang3@protonmail.com>
2024-11-21 16:17:52 +10:30
Lagrang3
937cf7a554 askrene: use the new MCF solver
Changelog-none: askrene: use the new MCF solver

Signed-off-by: Lagrang3 <lagrang3@protonmail.com>
2024-11-21 16:17:52 +10:30
Lagrang3
84a9476311 askrene: add mcf_refinement to the public API
Changelog-none: askrene: add mcf_refinement to the public API

Signed-off-by: Lagrang3 <lagrang3@protonmail.com>
2024-11-21 16:17:52 +10:30
Lagrang3
2142094e43 askrene: fix bug, not all arcs exists
We use an arc "array" in the graph structure, but not all arc indexes
correspond to real topological arcs. We must be careful when iterating
through all arcs, and check if they are enabled before making operations
on them.

Changelog-None: askrene: fix bug, not all arcs exists

Signed-off-by: Lagrang3 <lagrang3@protonmail.com>
2024-11-21 16:17:52 +10:30
Lagrang3
e655fe7bbd askrene: add bigger test for MCF
Using zlib to read big test case file.

Changelog-None: askrene: add bigger test for MCF

Signed-off-by: Lagrang3 <lagrang3@protonmail.com>
2024-11-21 16:17:52 +10:30
Lagrang3
2ea8e49683 askrene: add a MCF refinement
Add a new function to compute a MCF using a more general description of
the problem. I call it mcf_refinement because it can start with a
feasible flow (though this is not necessary) and adapt it to achieve
optimality.

Changelog-None: askrene: add a MCF refinement

Signed-off-by: Lagrang3 <lagrang3@protonmail.com>
2024-11-21 16:17:52 +10:30
Lagrang3
1dfa562cd9 askrene algorithm add helper for flow conservation
Changelog-None: askrene algorithm add helper for flow conservation

Signed-off-by: Lagrang3 <lagrang3@protonmail.com>
2024-11-21 16:17:52 +10:30
Lagrang3
42d075cc97 askrene: add a simple MCF solver
Changelog-EXPERIMENTAL: askrene: add a simple MCF solver

Signed-off-by: Lagrang3 <lagrang3@protonmail.com>
2024-11-21 16:17:52 +10:30
Lagrang3
8558299dec askrene: add algorithm to compute feasible flow
Changelog-EXPERIMENTAL: askrene: add algorithm to compute feasible flow

Signed-off-by: Lagrang3 <lagrang3@protonmail.com>
2024-11-21 16:17:52 +10:30
Lagrang3
f4f2985bdf askrene: add dijkstra algorithm
Changelog-EXPERIMENTAL: askrene: add dijkstra algorithm

Signed-off-by: Lagrang3 <lagrang3@protonmail.com>
2024-11-21 16:17:52 +10:30
Lagrang3
507153a1cd askrene: add graph algorithms module
Changelog-EXPERIMENTAL: askrene: add graph algorithms module

Signed-off-by: Lagrang3 <lagrang3@protonmail.com>
2024-11-21 16:17:52 +10:30
Lagrang3
59ce410699 askrene: add priorityqueue
It is just a copy-paste of "dijkstra" but the name
implies what it actually is. Not an implementation of minimum cost path
Dijkstra algorithm, but a helper data structure.
I keep the old "dijkstra.h/c" files for the moment to avoid breaking the
current code.

Changelog-EXPERIMENTAL: askrene: add priorityqueue

Signed-off-by: Lagrang3 <lagrang3@protonmail.com>
2024-11-21 16:17:52 +10:30
Lagrang3
32548cf02b askrene: add a new graph abstraction
Changelog-EXPERIMENTAL: askrene new graph abstraction

Signed-off-by: Lagrang3 <lagrang3@protonmail.com>
2024-11-21 16:17:52 +10:30
Rusty Russell
799acc90e6 lightningd: tell gossipd channel is closed if it tells us about our channel and is wrong.
While we have (I hope!) fixed the underlying sync problem, this can still happen with
older gossip.  So now we tell it the channel is dead, so it won't happen more than once.

Fixes: #7703
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-11-21 15:42:06 +10:30
Alex Myers
ead5dbf6a2 pytest: allow additional gossip filters
in test_gossip_force_broadcast_channel_msgs now that the seeker
is asking for periodic full gossip syncs.
2024-11-21 14:23:57 +10:30
Alex Myers
84b0dace31 gossipd: seeker: rotate worst gossiper every 30 minutes
This will allow all gossipers to be rotated in ~5 hours similar to
how it operated with half as many gossip streaming peers.
2024-11-21 14:23:57 +10:30
Alex Myers
323f23cf8f gossipd: seeker: rotate out the worst performing gossiper
Previously they were chosen at random.  We should instead
prefer to strop streaming from the peer who has provided
the least novel gossip.
2024-11-21 14:23:57 +10:30
Alex Myers
04180c1cad gossipd: add separate counter for unsolicted gossip
This will be used to drop underperforming gossipers instead
of choosing at random.
2024-11-21 14:23:57 +10:30
Alex Myers
995648911e gossipd: seeker: choose a new node when resyncing 2024-11-21 14:23:57 +10:30
Alex Myers
be694cba3a gossipd: seeker: add hourly full gossip resync from a random peer
This can help us backfill any missing gossip if our current
peers haven't been the most reliable.

Changelog-Changed: Gossipd requests a full sync from a random peer every hour.
2024-11-21 14:23:57 +10:30
Alex Myers
80bde554a4 gossipd: Increase gossiping peers to 10
Based on gossip sync data from random network peers, listening to only 5
peers will not reliably catch all gossip traffic.  For now, add extra
redundancy.
2024-11-21 14:23:57 +10:30
Dusty Daemon
d04e64670d splice: tx_abort no longer reestablishes
As per eclair implementation we skip `channel_reestablish` and go straight into the channel for `tx_abort` events.

Changelog-None
2024-11-21 14:15:36 +10:30
Dusty Daemon
6d63e68e99 splice: Update messages to spec
Changelog-Changed: Splicing moved from test numbers to spec numbers.
2024-11-21 14:15:36 +10:30
Dusty Daemon
dcdf7db65f splice: Enable remote funding key rotation
Allows our peer to change their funding pub key during a splice.

Changelog-Changed: Support added for peers that wish to rotate their funding pubkey during a splice.
2024-11-21 14:15:36 +10:30
Dusty Daemon
03d7d8f45a splice: Update funding pubkey on splice lock
Set the remote funding pubkey on both lightningd and channeld when mutual splice lock is achieved.

This will be needed once rotating funding keys is enabled during splicing

Changelog-None.
2024-11-21 14:15:36 +10:30
Dusty Daemon
5f330b3cd6 channeld: tx_abort should skip reestablish
`tx_abort` should not send reestablish message and instead go into ‘reconnect only mode’

Changelog-None
2024-11-21 14:15:36 +10:30
Dusty Daemon
d04478f99e splice: Enable shared tx on interactivetx
By placing the funding tx into `interactivetx`, the message will be compressed by only sending the txid via tlvs.

Changelog-None
2024-11-21 14:15:36 +10:30
Dusty Daemon
90c786f61b channeld: Move tx lookup function up
This function needs to be used earlier in the file so it is moved vertically up.

Chanelog-None
2024-11-21 14:15:36 +10:30
Dusty Daemon
9b06a85f54 splice: Update find_channel_output for rotating funding key
We need to differentiate the funding pubkey since we allow the peer to rotate it now.

Changelog-None
2024-11-21 14:15:36 +10:30
Dusty Daemon
2bb5d8ac67 splice: Update commit sigs to use dynamic remote funding pubkey.
Update the sending and receiving of commit sigs to use dyniamic funding pubkeys incase our remote peer rotates theirs during a splice.

Changelog-None
2024-11-21 14:15:36 +10:30
Dusty Daemon
7a8e377b81 splice: Update commitment_signed_tlvs
As per eclair spec proposal.
1) A renaming to `funding_txid`
2) Adding of `batch_size` to indicate how many commitment_signed msgs are expected.

Changelog-None
2024-11-21 14:15:36 +10:30
Dusty Daemon
2b41ada941 splice: Add new funding output balance
The prior spec left this value at 0 to be calculted later but the current spec requires we fill it in in advance.

Changelog-None
2024-11-21 14:15:36 +10:30
Dusty Daemon
2b3cb8b8a8 splice: Update splice signature msg type
Update to use spec signature type.

Changelog-None
2024-11-21 14:15:36 +10:30
Dusty Daemon
d077fd59c9 splice: Remove blockhash from peer msg
This is no longer used.

Changelog-None
2024-11-21 14:15:36 +10:30
Dusty Daemon
aea35536c0 channeld: Update commitsigs to support remote_funding
Since funding keys can be rotated during splice, commit sig routines must be able to handle a dynamic value for the funding keys.

Changelog-None
2024-11-21 14:15:36 +10:30
Dusty Daemon
a21ae33b2d channeld: Add dynamic funding_pubkeys to channel_txs
In anticipation of adding support for rotating funding pubkeys during a splice, `channel_txs` is updated to support specifying these manually instead of using the channel’s funding pubkeys.

Changelog-None
2024-11-21 14:15:36 +10:30
Dusty Daemon
42440e3bee splice: Pass remote_funding between ld and channeld
Update lightningd and channeld interface to pass the remote funding pubkey back and forth to both daemons.

Changelog-None
2024-11-21 14:15:36 +10:30
Dusty Daemon
17d2b24ebb channeld: Add remote_funding to inflight
Channeld stores its own cache of `inflight` and that needs to have a copy of `remote_funding` as well.

Since copying a secp256k1 pubkey isn’t documented and `copy_inflight` isn’t used anyway — we’re dropping `copy_inflight`.

Changelog-None
2024-11-21 14:15:36 +10:30
Dusty Daemon
ba3bd750fa channeld: Store remote_funding for splice
Instead of assuming the remote funding pubkey does not change during splice, we store the new pubkey in the splice object.

Changelog-None
2024-11-21 14:15:36 +10:30
Dusty Daemon
2e92fdc507 interactivetx: Add support for shared prevtx
It is possible for prevtx to be larger than max packet size, so for shared outputs (currently only the funding tx) we add support for sending the `txid` only across the wire and filling in the prevtx locally.

Changelog-None
2024-11-21 14:15:36 +10:30
Dusty Daemon
560ca00a2b splice: Add remote_funding to database
Enable storing the remote funding pubkey in DB if the channel peer decides to change it during splicing. It needs to be in DB incase of restarts mid-splice.

Changelog-None
2024-11-21 14:15:36 +10:30
Dusty Daemon
7d1a43d5d5 channeld: Fix tx_abort encoding
Switch to using same message format for `tx_abort` that wire_error and wire_warning use.

Changelog-None
2024-11-21 14:15:36 +10:30
Dusty Daemon
4b3643d209 splice: Clean up error messages for RPC
Added and updated error messages when splicing to make it more clear to the user why a splice is failing.

Changelog-Changed: Improved error messaging for splice commands.
2024-11-21 14:15:36 +10:30
Rusty Russell
2bf1053cdb offers: update block height correctly.
As we can see from the previous test, l3 tells us why it rejected the payment:

```
lightningd-3 2024-11-19T03:56:27.151Z DEBUG   022d223620a359a47ff7f7ac447c85c46c923da53389221a0054c11c1e3ca31d59-chan#1: Failing HTLC because of an invalid payload (TLV 10 pos 104): cltv_expiry 136 > payment_constraint 130
```

It turns out, we were not updating the block height in the plugin!

Without this, when we create a (non-dummy) blinded path we set a
too-low CLTV restriction, and it doesn't work after a few blocks!

Note we were actually triggering this error in the xpay tests!

Reported-by: Vincenzo Palazzo
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
Changelog-Fixed: Offers: Receiving bolt12 payments where we have no public channels would fail a few blocks after startup.
2024-11-20 12:29:27 +01:00
Vincenzo Palazzo
6f4f33d06b test: reproduce WIRE_INVALID_ONION_PAYLOAD
```
>           raise RpcError(method, payload, resp['error'])
E           pyln.client.lightning.RpcError: RPC call failed: method: pay, payload: {'bolt11': 'lni1qqgvsykv6pslpmzq73597z0ws2qv5q3qqc3xu3s3rg94nj40zfsy866mhu5vxne6tcej5878k2mneuvgjy8ssqgzpg48getnw30k7enxv4e97amfw3597urjd9mxzar9ta3ksctwdejkcu6ld46kcaredphhqvssacp462c3jt0m5y6wzrj5pp6axehtez7r20265antsrqfpvuu8fwcshgzqjushll8xx9x356tn40gk9mxzkyua9ajtrdpyhm3uaj9nvj0fm9qyqnjp20gp6gr2qsmfas7j086jvkmszqgyys3uht6jq7g4p6vsg7fyyqrx76aulp40m9uxejn57eyczy6v6hqmxr8xx273l480kd5zcl0g9hqp3d9qnsrj40gmeshx0w7fu6j9cfthksz2xv78wxr4ae4wrc3lht8lryc2kxxdpxvs3tpdepm0asuvp0l25fqqvjumjneecjg9etepcu426t2ueu6p3escfrxl9ggnkh5k2vm929tnt26dx66nt67kfy5lgx99py2jhqalaqkyypjeu2artvufgydym4tryv0wvkca78ac64mjeqt70d3wsmjcjgnqnjsyqrzymjxzydqkkw24ufxqslttwlj3s608f0rx2slc7etw0833zgs7kppqd350d9wur2l6mkanmpsswv4xrc49kaq6ey9sfn3rg3z8afgng8fdg8aqr7sxhftzxfdlwsnfcgw2sy8t5mxa0ytcdfat2nkdwqvpy9nnsa9mzzaqtyu8wy0yul9hk026znqy6pn6xd2fpxva7jjcpmvqugeewk7emufyqsru03er082j6ya0p694k6qu858hl0g9rt7g2y042ppzyhdv4qdv99qqs3scf49sff7vg27zlmx6n3kgywrh3s82rwgpza2s8jmqqx72ah0kurp94rj7dlxq438nnm34w78kq7hwu53chx0aqh824eqcsgmq9j2fyvsqttg4yksstnk7h7ga5as69fhemltg0m9hqnn2yxr0lxv70293l7ryqpjfamk2k4mzgax8txef7zcxdzjn0wg7te2cx98ft9cyhk0hquzypasww8m40kyzyqvahtzamflylsygnny5gwqqqqqqyqqqqq2qq9sqqqqqqqqqqqqqqqqqqp6tqqqqqqq5szxdnxnuk5zpctsclfcs4yx0kcvz8nckast2ueswxftuelh49su6sqs2vlzs8ha4gqs9vppqvk0zhg6m8z2prfxa2cerrmn9k803lwx4wukgzlnmvt5xukyjycyauzqwvm6pxlfpfffgktvj3wkurcwrqcp0537hnkd8pnm7tsa0zcklua9zv338cjuphz38wml6tlr8xgdzxdsqh0ks2pns2zkn3c52crfcfs'}, error: {'code': 203, 'message': 'failed: WIRE_INVALID_ONION_PAYLOAD (reply from remote)', 'id': 1, 'failcode': 16406, 'failcodename': 'WIRE_INVALID_ONION_PAYLOAD', 'bolt12': 'lni1qqgvsykv6pslpmzq73597z0ws2qv5q3qqc3xu3s3rg94nj40zfsy866mhu5vxne6tcej5878k2mneuvgjy8ssqgzpg48getnw30k7enxv4e97amfw3597urjd9mxzar9ta3ksctwdejkcu6ld46kcaredphhqvssacp462c3jt0m5y6wzrj5pp6axehtez7r20265antsrqfpvuu8fwcshgzqjushll8xx9x356tn40gk9mxzkyua9ajtrdpyhm3uaj9nvj0fm9qyqnjp20gp6gr2qsmfas7j086jvkmszqgyys3uht6jq7g4p6vsg7fyyqrx76aulp40m9uxejn57eyczy6v6hqmxr8xx273l480kd5zcl0g9hqp3d9qnsrj40gmeshx0w7fu6j9cfthksz2xv78wxr4ae4wrc3lht8lryc2kxxdpxvs3tpdepm0asuvp0l25fqqvjumjneecjg9etepcu426t2ueu6p3escfrxl9ggnkh5k2vm929tnt26dx66nt67kfy5lgx99py2jhqalaqkyypjeu2artvufgydym4tryv0wvkca78ac64mjeqt70d3wsmjcjgnqnjsyqrzymjxzydqkkw24ufxqslttwlj3s608f0rx2slc7etw0833zgs7kppqd350d9wur2l6mkanmpsswv4xrc49kaq6ey9sfn3rg3z8afgng8fdg8aqr7sxhftzxfdlwsnfcgw2sy8t5mxa0ytcdfat2nkdwqvpy9nnsa9mzzaqtyu8wy0yul9hk026znqy6pn6xd2fpxva7jjcpmvqugeewk7emufyqsru03er082j6ya0p694k6qu858hl0g9rt7g2y042ppzyhdv4qdv99qqs3scf49sff7vg27zlmx6n3kgywrh3s82rwgpza2s8jmqqx72ah0kurp94rj7dlxq438nnm34w78kq7hwu53chx0aqh824eqcsgmq9j2fyvsqttg4yksstnk7h7ga5as69fhemltg0m9hqnn2yxr0lxv70293l7ryqpjfamk2k4mzgax8txef7zcxdzjn0wg7te2cx98ft9cyhk0hquzypasww8m40kyzyqvahtzamflylsygnny5gwqqqqqqyqqqqq2qq9sqqqqqqqqqqqqqqqqqqp6tqqqqqqq5szxdnxnuk5zpctsclfcs4yx0kcvz8nckast2ueswxftuelh49su6sqs2vlzs8ha4gqs9vppqvk0zhg6m8z2prfxa2cerrmn9k803lwx4wukgzlnmvt5xukyjycyauzqwvm6pxlfpfffgktvj3wkurcwrqcp0537hnkd8pnm7tsa0zcklua9zv338cjuphz38wml6tlr8xgdzxdsqh0ks2pns2zkn3c52crfcfs', 'raw_message': '40160a0068', 'created_at': 1724699621, 'destination': '032cf15d1ad9c4a08d26eab1918f732d8ef8fdc6abb9640bf3db174372c491304e', 'payment_hash': 'e170c7d38854867db0c11e78b760b573307192be67f7a961cd4010533e281efd', 'status': 'failed', 'amount_msat': 3, 'amount_sent_msat': 0, 'erring_index': 2, 'erring_node': '035d2b1192dfba134e10e540875d366ebc8bc353d5aa766b80c090b39c3a5d885d'}

contrib/pyln-client/pyln/client/lightning.py:416: RpcError
```

Signed-off-by: Vincenzo Palazzo <vincenzopalazzodev@gmail.com>
2024-11-20 12:29:27 +01:00
Rusty Russell
1160e35669 lightningd: send errors inside blinded paths correctly.
Don't reply with update_fail_malformed_htlc, even though WIRE_INVALID_ONION_BLINDING
has BADONION set.  Fail it with a normal error message.

This fixes a known FIXME.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
Changelog-Fixed: Protocol: entry to blinded paths return more useful errors (e.g if it's the final node, you get a real error, otherwise you get invalid_onion_blinding).
2024-11-20 12:29:27 +01:00
Rusty Russell
e38f5d8c27 common: provide readable explanation when onion payload is invalid.
I had to use fprintf, which is terrible.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-11-20 12:29:27 +01:00
Rusty Russell
9ed7260328 pytest: fix test_pay tests now we've deprecated experimental-offers.
The test was merged after it was deprecated, and autogenerate-rpc-examples isn't
run by CI.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-11-20 17:34:24 +10:30
Rusty Russell
ba7bf334b1 fetchinvoice: check better.
We do a lot more parameter checking than simply parsing, so use
param_check().

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-11-19 22:54:22 +01:00
Vincenzo Palazzo
e76a334609 tests: add the test for fetching invoice with metadata
Signed-off-by: Vincenzo Palazzo <vincenzopalazzodev@gmail.com>
2024-11-19 22:54:22 +01:00
Vincenzo Palazzo
6f0dbbb20f bolt12: allow to inject payer_metadata
Payer metadata is a field that controls the payer ID
provided during the fetchinvoice process.

There are use cases where this is highly useful, such as
proving that the payer has paid for the correct item.

Imagine visiting a merchant's website to pay for multiple offers, where
one of these offers is a default offer (with no description and no set amount).

In this scenario, the merchant could claim not to have received
payment for a specific item. Since the same offer may be used to
fetch invoices for different products, there needs to be a way to
identify which product the invoice corresponds to.

With this commit, it will be possible to inject payer metadata,
which helps solve the issue described above.

For example, possible payer metadata could be `to_hex(b"{payer_node_id}.{product_id}.{created_at}")`.

Changelog-Added: JSON-RPC: `fetchinvoice` allows setting invreq_metadata via `payer_metadata` parameter.
Signed-off-by: Vincenzo Palazzo <vincenzopalazzodev@gmail.com>
2024-11-19 22:54:22 +01:00
Christian Decker
d27aa9888f db: Correct the name of the db_exec_prepared span name 2024-11-19 22:46:39 +01:00
Rusty Russell
1b2d5acf16 askrene: don't create duplicate layers if xpay creates layer before we load them.
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-11-19 17:51:18 +10:30
Rusty Russell
1380d36898 xpay: don't try to timeout things until after we have created xpay layer.
```
lightningd-1 2024-11-19T05:21:16.313Z DEBUG   lightningd: Looking for [askrene,layers]
lightningd-1 2024-11-19T05:21:16.314Z DEBUG   lightningd: Got [askrene,layers,xpay]
lightningd-1 2024-11-19T05:21:16.314Z DEBUG   lightningd: Printing
lightningd-1 2024-11-19T05:21:16.315Z **BROKEN** plugin-cln-xpay: askrene-age failed with {\"code\":-32602,\"message\":\"layer: Unknown layer: invalid token '\\\"xpay\\\"'\"}
lightningd-1 2024-11-19T05:21:16.318Z DEBUG   plugin-cln-askrene: datastore = {\"datastore\":[{\"key\":[\"askrene\",\"layers\",\"xpay\"],\"generation\":13,\"hex\":\"000300001000003f47af0100000000673c1fea010000000000d1b0d4000003000000000ce5066e0000000000673c1fea010000000000d1b0d400000300001000001a47050000000000673c1fea010000000000d1b0d400000300003f00005a72b40100000000673c1fea010000000000d1b0d400000300000000005a07e80100000000673c1fea010000000000d1b0d400000300001a0000e3564c0100000000673c1fea010000000000d1b0d40000030000e3000db69cf50000000000673c1fea0001000000000100637e\"}]}
lightningd-1 2024-11-19T05:21:16.318Z DEBUG   plugin-cln-askrene: Loaded level xpay (203 bytes)
lightningd-1 2024-11-19T05:21:16.391Z INFO    plugin-cln-xpay: Killing plugin: exited during normal operation
```

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-11-19 17:51:18 +10:30
Rusty Russell
6c347a4050 pytest: fix flake in test_gossip_pruning
We actually pruned before we got all the channels.  Extend the pruning time,
which unfortunately makes the test slower.

```
2024-11-18T02:13:11.7013278Z node_factory = <pyln.testing.utils.NodeFactory object at 0x7ff72969e820>
2024-11-18T02:13:11.7014386Z bitcoind = <pyln.testing.utils.BitcoinD object at 0x7ff72968fe20>
2024-11-18T02:13:11.7014996Z 
2024-11-18T02:13:11.7015271Z     def test_gossip_pruning(node_factory, bitcoind):
2024-11-18T02:13:11.7016222Z         """ Create channel and see it being updated in time before pruning
2024-11-18T02:13:11.7017037Z         """
2024-11-18T02:13:11.7017871Z         l1, l2, l3 = node_factory.get_nodes(3, opts={'dev-fast-gossip-prune': None,
2024-11-18T02:13:11.7018971Z                                                      'allow_bad_gossip': True})
2024-11-18T02:13:11.7019634Z     
2024-11-18T02:13:11.7020236Z         l1.rpc.connect(l2.info['id'], 'localhost', l2.port)
2024-11-18T02:13:11.7021153Z         l2.rpc.connect(l3.info['id'], 'localhost', l3.port)
2024-11-18T02:13:11.7021806Z     
2024-11-18T02:13:11.7022226Z         scid1, _ = l1.fundchannel(l2, 10**6)
2024-11-18T02:13:11.7022886Z         scid2, _ = l2.fundchannel(l3, 10**6)
2024-11-18T02:13:11.7023458Z     
2024-11-18T02:13:11.7023907Z         mine_funding_to_announce(bitcoind, [l1, l2, l3])
2024-11-18T02:13:11.7025183Z         l1_initial_cupdate_timestamp = only_one(l1.rpc.listchannels(source=l1.info['id'])['channels'])['last_update']
2024-11-18T02:13:11.7026179Z     
2024-11-18T02:13:11.7027358Z         # Get timestamps of initial updates, so we can ensure they change.
2024-11-18T02:13:11.7028171Z         # Channels should be activated locally
2024-11-18T02:13:11.7029326Z >       wait_for(lambda: [c['active'] for c in l1.rpc.listchannels()['channels']] == [True] * 4)
```

We can see in logs, it actually started pruning already:

```
2024-11-18T02:13:11.9622477Z lightningd-1 2024-11-18T01:52:03.570Z DEBUG   gossipd: Pruning channel 105x1x0 from network view (ages 1731894723 and 0)
```

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-11-19 17:51:18 +10:30
Rusty Russell
79d39e0296 pytest: fix flake in test_onionmessage_ratelimit
Sometimes l1 ratelimits before l2, and l2 receives the warning message, not l1:

```
>       assert l1.daemon.is_in_log('WARNING: Ratelimited onion_message: exceeded one per 250msec')
E       AssertionError: assert None
E        +  where None = <bound method TailableProc.is_in_log of <pyln.testing.utils.LightningD object at 0x7f13435f45b0>>('WARNING: Ratelimited onion_message: exceeded one per 250msec')
E        +    where <bound method TailableProc.is_in_log of <pyln.testing.utils.LightningD object at 0x7f13435f45b0>> = <pyln.testing.utils.LightningD object at 0x7f13435f45b0>.is_in_log
E        +      where <pyln.testing.utils.LightningD object at 0x7f13435f45b0> = <fixtures.LightningNode object at 0x7f13435cbb80>.daemon
...
lightningd-1 2024-11-19T00:45:43.721Z DEBUG   022d223620a359a47ff7f7ac447c85c46c923da53389221a0054c11c1e3ca31d59-connectd: peer_in WIRE_ONION_MESSAGE
lightningd-1 2024-11-19T00:45:43.721Z DEBUG   022d223620a359a47ff7f7ac447c85c46c923da53389221a0054c11c1e3ca31d59-connectd: peer_out WIRE_WARNING
lightningd-2 2024-11-19T00:45:43.722Z DEBUG   0266e4598d1d3c415f572a8488830b60f7e744ed9235eb0b1ba93283b315c03518-connectd: peer_out WIRE_ONION_MESSAGE
lightningd-2 2024-11-19T00:45:43.722Z DEBUG   connectd: REPLY WIRE_CONNECTD_INJECT_ONIONMSG_REPLY with 0 fds
lightningd-2 2024-11-19T00:45:43.722Z DEBUG   0266e4598d1d3c415f572a8488830b60f7e744ed9235eb0b1ba93283b315c03518-connectd: peer_in WIRE_WARNING
lightningd-2 2024-11-19T00:45:43.722Z INFO    0266e4598d1d3c415f572a8488830b60f7e744ed9235eb0b1ba93283b315c03518-connectd: Received WIRE_WARNING: WARNING: Ratelimited onion_message: exceeded one per 250msec
```

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-11-19 17:51:18 +10:30
Rusty Russell
c4f8716a55 pytest: fix race in test_autoclean.
We can see the log message about cleanup just after the test ends.

```
>       assert l3.rpc.autoclean_status()['autoclean']['expiredinvoices']['cleaned'] == 1
E       assert 0 == 1

tests/test_plugin.py:3232: AssertionError
```
...
```

lightningd-3 2024-11-18T07:52:55.402Z INFO    lightningd: setconfig: autoclean-cycle 10 (updated /tmp/ltests-ao0p8pem/test_autoclean_1/lightning-3/regtest/config:4)
...
lightningd-3 2024-11-18T07:52:59.747Z DEBUG   022d223620a359a47ff7f7ac447c85c46c923da53389221a0054c11c1e3ca31d59-connectd: peer_out WIRE_QUERY_CHANNEL_RANGE
lightningd-3 2024-11-18T07:52:59.747Z DEBUG   022d223620a359a47ff7f7ac447c85c46c923da53389221a0054c11c1e3ca31d59-gossipd: reply_channel_range 0+109 (of 0+109) 2 scids
lightningd-3 2024-11-18T07:52:59.747Z DEBUG   gossipd: seeker: state = NORMAL No unannounced nodes
{'github_repository': 'ElementsProject/lightning', 'github_sha': '0729de783e95c5208b1706f7d27b23904596bb71', 'github_ref': 'refs/pull/7835/merge', 'github_ref_name': 'HEAD', 'github_run_id': 11887300979, 'github_head_ref': 'guilt/fix-flakes8', 'github_run_number': 11566, 'github_base_ref': 'master', 'github_run_attempt': '1', 'testname': 'test_autoclean', 'start_time': 1731916359, 'end_time': 1731916385, 'outcome': 'fail'}
--------------------------- Captured stdout teardown ---------------------------
lightningd-3 2024-11-18T07:53:05.503Z DEBUG   plugin-autoclean: cleaned 1 from expiredinvoices
lightningd-3 2024-11-18T07:53:05.503Z DEBUG   plugin-autoclean: setting next timer
```

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-11-19 17:51:18 +10:30
Rusty Russell
1e8cbf2645 lightningd: don't access after free on plugin crash
tests/test_plugin.py::test_important_plugin does this, and it's inelegant:

```
lightningd-1 2024-11-18T07:33:09.433Z **BROKEN** plugin-fail_by_itself.py: Plugin marked as important, shutting down lightningd!
lightningd-1 2024-11-18T07:33:09.451Z DEBUG   lightningd: io_break: lightningd_exit
lightningd-1 2024-11-18T07:33:09.533Z DEBUG   connectd: REPLY WIRE_CONNECTD_START_SHUTDOWN_REPLY with 0 fds
lightningd-1 2024-11-18T07:33:09.575Z DEBUG   lightningd: io_break: connectd_start_shutdown_reply
lightningd-1 2024-11-18T07:33:09.802Z DEBUG   lightningd: Looking for [autoclean,failedforwards,num]
{'github_repository': 'ElementsProject/lightning', 'github_sha': '0729de783e95c5208b1706f7d27b23904596bb71', 'github_ref': 'refs/pull/7835/merge', 'github_ref_name': 'HEAD', 'github_run_id': 11887300979, 'github_head_ref': 'guilt/fix-flakes8', 'github_run_number': 11566, 'github_base_ref': 'master', 'github_run_attempt': '1', 'testname': 'test_important_plugin', 'start_time': 1731915163, 'end_time': 1731915190, 'outcome': 'fail'}
----------------------------- Captured stderr call -----------------------------
No plugin for askrene-create-layer ?
Lost connection to the RPC socket.Reading JSON input: Connection reset by peerReading JSON input: Connection reset by peerReading JSON input: Connection reset by peerReading JSON input: Connection reset by peer
--------------------------- Captured stdout teardown ---------------------------
------------------------------- Valgrind errors --------------------------------
Valgrind error file: valgrind-errors.28639
==28639== Invalid read of size 8
==28639==    at 0x168310: command_exec (jsonrpc.c:808)
==28639==    by 0x168A98: rpc_command_hook_final (jsonrpc.c:954)
==28639==    by 0x1AD48C: plugin_hook_call_next (plugin_hook.c:196)
==28639==    by 0x1AD407: plugin_hook_callback (plugin_hook.c:183)
==28639==    by 0x1A6074: plugin_response_handle (plugin.c:663)
==28639==    by 0x1A62F0: plugin_read_json_one (plugin.c:775)
==28639==    by 0x1A652D: plugin_read_json (plugin.c:826)
==28639==    by 0x390200: next_plan (io.c:60)
==28639==    by 0x390E56: do_plan (io.c:422)
==28639==    by 0x390EBD: io_ready (io.c:439)
==28639==    by 0x3932F1: io_loop (poll.c:455)
==28639==    by 0x1ABBE4: shutdown_plugins (plugin.c:2588)
==28639==  Address 0x5d25a20 is 48 bytes inside a block of size 88 free'd
==28639==    at 0x484B27F: free (in /usr/libexec/valgrind/vgpreload_memcheck-amd64-linux.so)
==28639==    by 0x3A31FB: del_tree (tal.c:456)
==28639==    by 0x3A317B: del_tree (tal.c:447)
==28639==    by 0x3A34DC: tal_free (tal.c:532)
==28639==    by 0x1ABAF3: shutdown_plugins (plugin.c:2575)
==28639==    by 0x16E0D3: main (lightningd.c:1514)
==28639==  Block was alloc'd at
==28639==    at 0x4848899: malloc (in /usr/libexec/valgrind/vgpreload_memcheck-amd64-linux.so)
==28639==    by 0x3A2BCA: allocate (tal.c:256)
==28639==    by 0x3A3252: tal_alloc_ (tal.c:473)
==28639==    by 0x1A815E: plugin_rpcmethod_add (plugin.c:1425)
==28639==    by 0x1A83F9: plugin_rpcmethods_add (plugin.c:1470)
==28639==    by 0x1A965A: plugin_parse_getmanifest_response (plugin.c:1850)
==28639==    by 0x1A971F: plugin_manifest_cb (plugin.c:1872)
==28639==    by 0x1A6074: plugin_response_handle (plugin.c:663)
==28639==    by 0x1A62F0: plugin_read_json_one (plugin.c:775)
==28639==    by 0x1A652D: plugin_read_json (plugin.c:826)
==28639==    by 0x390200: next_plan (io.c:60)
==28639==    by 0x390E56: do_plan (io.c:422)
==28639==
```

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-11-19 17:51:18 +10:30
Rusty Russell
1a5916cb81 pytest: try to fix flake in test_lightningd_still_loading
I can't reproduce this, but CI did (with Elements):

```
[gw3] linux -- Python 3.8.18 /home/runner/.cache/pypoetry/virtualenvs/cln-meta-project-AqJ9wMix-py3.8/bin/python

node_factory = <pyln.testing.utils.NodeFactory object at 0x7fd0e20f57f0>
bitcoind = <pyln.testing.utils.ElementsD object at 0x7fd0e307dbe0>
executor = <concurrent.futures.thread.ThreadPoolExecutor object at 0x7fd0e307da30>

    @pytest.mark.openchannel('v1')
    @pytest.mark.openchannel('v2')
    def test_lightningd_still_loading(node_factory, bitcoind, executor):
        """Test that we recognize we haven't got all blocks from bitcoind"""
    
        mock_release = Event()
    
        # This is slow enough that we're going to notice.
        def mock_getblock(r):
            conf_file = os.path.join(bitcoind.bitcoin_dir, 'bitcoin.conf')
            brpc = RawProxy(btc_conf_file=conf_file)
            if r['params'][0] == slow_blockid:
                mock_release.wait(TIMEOUT)
            return {
                "result": brpc._call(r['method'], *r['params']),
                "error": None,
                "id": r['id']
            }
    
        # Start it, establish channel, get extra funds.
        l1, l2, l3 = node_factory.get_nodes(3, opts=[{'may_reconnect': True,
                                                      'wait_for_bitcoind_sync': False},
                                                     {'may_reconnect': True,
                                                      'wait_for_bitcoind_sync': False},
                                                     {}])
        node_factory.join_nodes([l1, l2])
    
        # Balance l1<->l2 channel
        l1.pay(l2, 10**9 // 2)
    
        l1.stop()
    
        # Now make sure l2 is behind.
        bitcoind.generate_block(2)
        # Make sure l2/l3 are synced
        sync_blockheight(bitcoind, [l2, l3])
    
        # Make it slow grabbing the final block.
        slow_blockid = bitcoind.rpc.getblockhash(bitcoind.rpc.getblockcount())
        l1.daemon.rpcproxy.mock_rpc('getblock', mock_getblock)
    
        l1.start(wait_for_bitcoind_sync=False)
    
        # It will warn about being out-of-sync.
        assert 'warning_bitcoind_sync' not in l1.rpc.getinfo()
        assert 'warning_lightningd_sync' in l1.rpc.getinfo()
    
        # Make sure it's connected to l2 (otherwise we get TEMPORARY_CHANNEL_FAILURE)
        wait_for(lambda: only_one(l1.rpc.listpeers(l2.info['id'])['peers'])['connected'])
    
        # Payments will succced.
        l1.pay(l2, 1000)
>       assert l1.daemon.is_in_log(r"Sending HTLC while still syncing with bitcoin network \(104 vs 105\)")
E       AssertionError: assert None
E        +  where None = <bound method TailableProc.is_in_log of <pyln.testing.utils.LightningD object at 0x7fd0e20f9fa0>>('Sending HTLC while still syncing with bitcoin network \\(104 vs 105\\)')
E        +    where <bound method TailableProc.is_in_log of <pyln.testing.utils.LightningD object at 0x7fd0e20f9fa0>> = <pyln.testing.utils.LightningD object at 0x7fd0e20f9fa0>.is_in_log
E        +      where <pyln.testing.utils.LightningD object at 0x7fd0e20f9fa0> = <fixtures.LightningNode object at 0x7fd0e20f59d0>.daemon
```

What was in logs was:

```
lightningd-1 2024-11-18T05:33:50.634Z DEBUG   022d223620a359a47ff7f7ac447c85c46c923da53389221a0054c11c1e3ca31d59-chan#1: Sending HTLC while still syncing with bitcoin network (103 vs 105)
```

Implying that l1 was an extra block behind.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-11-19 17:51:18 +10:30
Rusty Russell
576d003cf0 pytest: fix flake in test_wumbo_channels
We need to wait for *l2* to see the channel in CHANNELD_NORMAL,
otherwise the array here is empty:

```
	chan = only_one([c for c in l1.rpc.listpeerchannels(l2.info['id'])['channels'] if c['state'] == 'CHANNELD_NORMAL'])
        amount = chan['funding']['local_funds_msat']
        assert amount > Millisatoshi(str((1 << 24) - 1) + "sat")
    
        # We should know we can spend that much!
        spendable = chan['spendable_msat']
        assert spendable > Millisatoshi(str((1 << 24) - 1) + "sat")
    
        # So should peer.
>       chan = only_one([c for c in l2.rpc.listpeerchannels(l1.info['id'])['channels'] if c['state'] == 'CHANNELD_NORMAL'])

tests/test_connection.py:3552: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

arr = []

    def only_one(arr):
        """Many JSON RPC calls return an array; often we only expect a single entry
        """
>       assert len(arr) == 1
E       AssertionError
```
2024-11-19 17:51:18 +10:30
Michael Schmoock
e79a275209 pytest: fix a test that broke because of docstring usage 2024-11-19 11:50:42 +10:30
Michael Schmoock
5fe0c1c41e pyln-client: adds testcase for usage in manifest and print_usage 2024-11-19 11:50:42 +10:30
Michael Schmoock
49aaab5128 pyln-client: refactors usage string generation to reduce code duplication 2024-11-19 11:50:42 +10:30
Michael Schmoock
19fb5d8ae7 pyln-client: adds description to methods via docstring
The old `long_description` was removed and deprecated a while ago
without adding a proper replacement for plugin developers.
The getmanifest JSON that was to be used for that only knows `name` and `usage`.

This PR adds an optional `description` parameter that will be filled
with the methods docstring `__doc__` (if set).

Example:

    @p.method("example")
    def some_method(...)
        """some description"""
        ...

Changelog-Add: optional description paramter to Plugin.Method
2024-11-19 11:50:42 +10:30
Matt Whitlock
67d667db90 tools/headerversions.c: fix build without SQLite
Commit 531845971c broke the build without
SQLite because this code:

	new = tal_fmt(NULL, template,
	              IF_SQLITE3(sqlite3_libversion_number()));

preprocesses into:

	new = tal_fmt(NULL, template,
	              );

which has a syntax error. Fix it by moving the comma into the macro
argument.

Fixes: 531845971c
Changelog-None
2024-11-19 09:48:31 +10:30
ShahanaFarooqui
2e52df41dd test: Fixed test plugin source paths for reckless 2024-11-19 09:06:28 +10:30
ShahanaFarooqui
047eb8bbeb ci: Update Python version from 3.8 to 3.10
Changelog-None.
2024-11-19 09:05:55 +10:30
ShahanaFarooqui
4bff697be9 ci: Update Ubuntu version from 20.04 to 22.04 2024-11-19 09:05:55 +10:30
ShahanaFarooqui
4e43b07ee4 ci: Adding missing jq dependency in script 2024-11-19 09:05:55 +10:30
ShahanaFarooqui
e352a72e5e shellcheck: shellcheck fixes 2024-11-19 09:05:55 +10:30
ShahanaFarooqui
61abfbcad1 ci: Removed CPP check script 2024-11-19 09:05:55 +10:30
Christian Decker
04b4f61308 db: Instrument the DB interactions to trace their execution 2024-11-18 17:46:40 +01:00
Rusty Russell
1b413502e0 lightningd: deprecate experimental-offers option.
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
Changelog-Deprecated: Config: `experimental-offers` (it's now the default).
2024-11-18 10:42:54 +01:00
Rusty Russell
0cc52bc281 pytest: don't set experimental-offers in tests: it's the default now.
And about to be deprecated.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-11-18 10:42:54 +01:00
Rusty Russell
46b0eb108b plugins: don't check for experimental-offers option: it's the default now.
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-11-18 10:42:54 +01:00
Rusty Russell
e254d91bd2 docs: no longer tell people experimental-offers is required.
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-11-18 10:42:54 +01:00
Rusty Russell
ca41414da4 offers: make it the default.
Changelog-Changed: offers: bolt12 now enabled by default (finally!)
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-11-18 10:42:54 +01:00
Rusty Russell
05fbcb4d9b xpay: make sure to call preapproveinvoice!
This is required for VLS which wants to know (and potentially decline) invoices
we're trying to pay.

As a nice side effect, our "check" command for xpay now does much more thorough
checking of arguments.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-11-18 11:03:26 +10:30
Rusty Russell
2c15dc0e5b xpay: make self-pay work.
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-11-18 11:03:26 +10:30
Rusty Russell
229fc3f2b4 xpay: make the xpay layer persistent.
As the first user of a persistent layer, this tripped tests which
assumed the datastore would be empty!

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-11-18 11:03:26 +10:30
Rusty Russell
c93153ec37 lightningd: allow builtin plugins to be stopped.
These are automatically marked "important", in the sense that we won't startup
if they are not working, but this wasn't meant to disallow stopping them.

Changelog-Changed: JSON-RPC: built-in plugins can now be stopped using "plugin stop".
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-11-18 11:03:26 +10:30
Rusty Russell
41e15b1ac9 xpay: age the "xpay" layer so we forget information older than 1 hour.
1 hour is what mpay uses, so stick with that for now.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-11-18 11:03:26 +10:30
Rusty Russell
c715253af7 xpay: option to steal easy commands from pay.
Note: won't work with grpc (or probably other tools), since the output
is different.  But good for testing.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
Changelog-Added: Config: option `xpay-handle-pay` can be used to call xpay when pay is used in many cases (but output is different from pay!)
2024-11-18 11:03:26 +10:30
Rusty Russell
090d605527 libplugin: allow aux_command use in init()
Because we initalized plugin->io_rpc_conn *after* calling plugin->init,
send_outreq would do a (harmless, in our case) wakeup on an uninitialized address:

```
==1164079== Conditional jump or move depends on uninitialised value(s)
==1164079==    at 0x1628FC: backend_wake (poll.c:227)
==1164079==    by 0x160B98: io_wake (io.c:384)
==1164079==    by 0x1160A8: ld_rpc_send (libplugin.c:255)
==1164079==    by 0x1187E0: send_outreq (libplugin.c:1099)
==1164079==    by 0x115041: init (xpay.c:1620)
```

Solution is simple: set plugin->io_rpc_conn to NULL, and don't wake it in this case.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-11-18 11:03:26 +10:30
Rusty Russell
64c1522597 xpay: don't use rpc_scan or jsonrpc_request_sync.
These will deadlock once we hook into rpc_command, so avoid them.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-11-18 11:03:26 +10:30
Rusty Russell
dd4d3940b1 xpay: implement partial payments.
Explicitly tell xpay to only make part of a payment.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-11-18 11:03:26 +10:30
Rusty Russell
47318a7875 xpay: add deadline.
We promised this in the schema originally, now support it.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-11-18 11:03:26 +10:30
Rusty Russell
06a9aa8907 pytest: test xpay with channeld_fakenet to pay top 100 nodes.
We also put broken status messages for invalid CLTVs and amounts in onions,
to catch them in CI.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-11-18 11:03:26 +10:30
Rusty Russell
e38ef42041 devtools: bolt11-cli encode command to make fake invoices.
This will let us make invoices for the fake network.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-11-18 11:03:26 +10:30
Rusty Russell
7c2407ef48 xpay: new plugin which uses askrene, injectpaymentonion.
Changelog-Added: Plugins: cln-xpay, with associated `xpay` command for payments.
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-11-18 11:03:26 +10:30
Rusty Russell
8c051c555e pyln-testing: don't skip renepay and askrene!
We called these `cln-renepay` and `cln-askrene` which meant we didn't
test them under valgrind!

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-11-18 11:03:26 +10:30
Rusty Russell
38d229df3d tools/generate-wire.py: make sure TLV array fields are allocated off TLV.
Otherwise the whole thing cannot be tal_steal() onto a different parent.

Here's the difference in generated files:

   --- ./wire/onion_wiregen.c.pre	2024-10-23 12:26:09.023176933 +1030
   +++ ./wire/onion_wiregen.c	2024-10-23 12:26:52.434828303 +1030
   @@ -128,7 +128,7 @@
     	blinded_path->path = num_hops ? tal_arr(blinded_path, struct blinded_path_hop *, 0) : NULL;
    	for (size_t i = 0; i < num_hops; i++) {
    		struct blinded_path_hop * tmp;
   -		tmp = fromwire_blinded_path_hop(blinded_path, cursor, plen);
   +		tmp = fromwire_blinded_path_hop(blinded_path->path, cursor, plen);
    		tal_arr_expand(&blinded_path->path, tmp);
    	}
    
   --- ./wire/bolt12_wiregen.c.pre	2024-10-23 12:26:09.079176474 +1030
   +++ ./wire/bolt12_wiregen.c	2024-10-23 12:26:52.612826902 +1030
   @@ -316,7 +316,7 @@
    	r->offer_paths = *plen ? tal_arr(r, struct blinded_path *, 0) : NULL;
    	while (*plen != 0) {
    		struct blinded_path * tmp;
   -		tmp = fromwire_blinded_path(r, cursor, plen);
   +		tmp = fromwire_blinded_path(r->offer_paths, cursor, plen);
    		tal_arr_expand(&r->offer_paths, tmp);
    	}
    }
   @@ -729,7 +729,7 @@
    	r->offer_paths = *plen ? tal_arr(r, struct blinded_path *, 0) : NULL;
    	while (*plen != 0) {
    		struct blinded_path * tmp;
   -		tmp = fromwire_blinded_path(r, cursor, plen);
   +		tmp = fromwire_blinded_path(r->offer_paths, cursor, plen);
    		tal_arr_expand(&r->offer_paths, tmp);
    	}
    }
   @@ -1052,7 +1052,7 @@
    	r->invreq_paths = *plen ? tal_arr(r, struct blinded_path *, 0) : NULL;
    	while (*plen != 0) {
    		struct blinded_path * tmp;
   -		tmp = fromwire_blinded_path(r, cursor, plen);
   +		tmp = fromwire_blinded_path(r->invreq_paths, cursor, plen);
    		tal_arr_expand(&r->invreq_paths, tmp);
    	}
    }
   @@ -1385,7 +1385,7 @@
    	r->offer_paths = *plen ? tal_arr(r, struct blinded_path *, 0) : NULL;
    	while (*plen != 0) {
    		struct blinded_path * tmp;
   -		tmp = fromwire_blinded_path(r, cursor, plen);
   +		tmp = fromwire_blinded_path(r->offer_paths, cursor, plen);
    		tal_arr_expand(&r->offer_paths, tmp);
    	}
    }
   @@ -1708,7 +1708,7 @@
    	r->invreq_paths = *plen ? tal_arr(r, struct blinded_path *, 0) : NULL;
    	while (*plen != 0) {
    		struct blinded_path * tmp;
   -		tmp = fromwire_blinded_path(r, cursor, plen);
   +		tmp = fromwire_blinded_path(r->invreq_paths, cursor, plen);
    		tal_arr_expand(&r->invreq_paths, tmp);
    	}
    }
   @@ -1781,7 +1781,7 @@
    	r->invoice_paths = *plen ? tal_arr(r, struct blinded_path *, 0) : NULL;
    	while (*plen != 0) {
    		struct blinded_path * tmp;
   -		tmp = fromwire_blinded_path(r, cursor, plen);
   +		tmp = fromwire_blinded_path(r->invoice_paths, cursor, plen);
    		tal_arr_expand(&r->invoice_paths, tmp);
    	}
    }
   @@ -1808,7 +1808,7 @@
    	r->invoice_blindedpay = *plen ? tal_arr(r, struct blinded_payinfo *, 0) : NULL;
    	while (*plen != 0) {
    		struct blinded_payinfo * tmp;
   -		tmp = fromwire_blinded_payinfo(r, cursor, plen);
   +		tmp = fromwire_blinded_payinfo(r->invoice_blindedpay, cursor, plen);
    		tal_arr_expand(&r->invoice_blindedpay, tmp);
    	}
    }
   @@ -1927,7 +1927,7 @@
    	r->invoice_fallbacks = *plen ? tal_arr(r, struct fallback_address *, 0) : NULL;
    	while (*plen != 0) {
    		struct fallback_address * tmp;
   -		tmp = fromwire_fallback_address(r, cursor, plen);
   +		tmp = fromwire_fallback_address(r->invoice_fallbacks, cursor, plen);
    		tal_arr_expand(&r->invoice_fallbacks, tmp);
    	}
    }
   
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-11-18 11:03:26 +10:30
Rusty Russell
99cc81b90a pytest: Allow a specific lightningd for DEBUG_SUBD
e.g. "lightningd-1:xpay" or even "1:xpay" means it will only apply to l1.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-11-18 11:03:26 +10:30
Rusty Russell
611e430754 lightningd: injectpaymentonion should fail on re-attempts.
This is clearer than transparently succeeding: the user might think they
paid twice.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-11-18 11:03:26 +10:30
Rusty Russell
d6152fdc40 lightningd: don't include empty error in onion returned on failed injectpaymentonion.
fail->msg can be NULL for local failures (the error message itself is more informative
in this case).  Use the generic "something went wrong" message.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-11-18 11:03:26 +10:30
Rusty Russell
ef475db478 common: sphinx_path_new to take explicit len.
Useful if associated_data is not a tal pointer (xpay wants this).

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-11-18 11:03:26 +10:30
Rusty Russell
80357911fb lightningd: fix clang 19 compile error.
```
Ubuntu clang version 19.1.0 (++20240901083933+6d7e428df611-1~exp1~20240901084058.28)
Target: x86_64-pc-linux-gnu
Thread model: posix
InstalledDir: /usr/lib/llvm-19/bin

./configure CC=clang-19
make -j17
<snip>
cc lightningd/offer.c
cc lightningd/signmessage.c
lightningd/subd.c:945:16: error: variable length array folded to constant array as an extension [-Werror,-Wgnu-folding-constant]
  945 |         char permfail[strlen("PERMFAIL")];
      |                       ^~~~~~~~~~~~~~~~~~
cc wallet/db.c
```

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
Changelog-Fixed: build: fix overzealous warning from clang 19.
2024-11-17 22:36:04 +10:30
ShahanaFarooqui
2dd0d4c88a test: listaddresses tests
Added a new test for listaddresses rpc.
2024-11-17 20:27:13 +10:30
ShahanaFarooqui
117dd748ba doc: Add schema for listaddresses 2024-11-17 20:27:13 +10:30
ShahanaFarooqui
fd27cda4f4 rpc: Added listaddresses command
Changelog-Added: New rpc `listaddresses` to list issued addresses from the node.
2024-11-17 20:27:13 +10:30
ShahanaFarooqui
af2f9601c6 wallet: list addresses query 2024-11-17 20:27:13 +10:30
ShahanaFarooqui
bb252983c2 wallet: insert addrtype ADDR_ALL for issued addresses 2024-11-17 20:27:13 +10:30
Rusty Russell
6da97e6461 wallet: save keytype when issuing new address.
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-11-17 20:27:13 +10:30
Rusty Russell
13af9bcfe7 lightningd: use P2TR for onchain tx spends.
Both for HTLC txs and the to-self outputs.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
Changelog-Changed: Wallet: Taproot addresses are used for unilateral-close change addresses.
2024-11-17 20:27:13 +10:30
Rusty Russell
836204b1f2 lightningd: use P2TR for anchor spends.
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-11-17 20:27:13 +10:30
Rusty Russell
ad1e9f7979 onchaind: don't get final_key_idx.
onchaind used to make its own txs, but doesn't any more.  This
parameter is useless.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-11-17 20:27:13 +10:30
ShahanaFarooqui
72345c5fbc gitignore: Ignore chaneld_fakenet 2024-11-17 20:27:13 +10:30
Rusty Russell
c4cbb8671a lightningd: actually deprecate old close fields.
Changelog-Deprecated: `close` `tx` and `txid` field (use `txs` and `txids`)
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-11-17 16:04:06 +10:30
Rusty Russell
c79a89d557 pytest: adapt tests to avoid deprecated APIs in close (tx and txid).
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-11-17 16:04:06 +10:30
Dusty Daemon
809f3b01d9 close: Print multiple txs; Fixes #6467
Changelog-Changed: `close` now outputs txs & txids of all closing transactions (splice candidates can cause there to be multiple).
2024-11-17 16:04:06 +10:30
Dusty Daemon
4500661bbf channeld: Add aggressive restart test
Changelog-None
2024-11-17 15:32:28 +10:30
niftynei
cb2163e439 bkpr: add bookkeeping assertions to splice in + out tests
Make sure that the fees and channel balances for splice ins and outs
work as expected.

Note this is for a single-sided splice.
Changelog-None: Tests!
2024-11-17 14:25:29 +10:30
Rusty Russell
fcebb33180 lightningd: deprecate decodepay.
It only works on BOLT11, and has long been replaced by the more
generic "decode".

Removing it will stop the confusion!

(Note: documentation claims it was introduced in 23.08, but that was
 wrong, as it's been in CLN since the beginning).

[ Fixup from: niftynei <niftynei@gmail.com> ]
Fixes: https://github.com/ElementsProject/lightning/issues/6419
Changelog-Deprecated: JSON-RPC: `decodepay`: use `decode`.
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-11-17 14:21:23 +10:30
Rusty Russell
374db239be Makefile: ensure that cln-grpc depends on msggen generated files.
Looks like a build race, where we use it before it's finished:

```
msggen cln-rpc/src/model.rs
error: this file contains an unclosed delimiter
    --> cln-grpc/src/server.rs:3661:7
     |
84   | {
     | - unclosed delimiter
...
3661 |     }
     |      ^
```
...

```
make: *** [plugins/Makefile:298: target/release/cln-grpc] Error 101
make: *** Waiting for unfinished jobs....
```

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-11-17 14:09:10 +10:30
Rusty Russell
fffb381a40 lightningd: help memleak scan into replay_tx hash table to avoid false positives.
```
**BROKEN** lightningd: MEMLEAK: 0x5557327d1428
**BROKEN** lightningd:   label=lightningd/onchain_control.c:352:struct replay_tx
**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/lightningd/onchain_control.c:352 (replay_watch_tx)
**BROKEN** lightningd:     /home/runner/work/lightning/lightning/lightningd/onchain_control.c:1816 (onchaind_funding_spent)
**BROKEN** lightningd:     /home/runner/work/lightning/lightning/lightningd/onchain_control.c:1860 (onchaind_replay_channels)
**BROKEN** lightningd:     /home/runner/work/lightning/lightning/lightningd/lightningd.c:1407 (main)
**BROKEN** lightningd:   parents:
**BROKEN** lightningd:     lightningd/onchain_control.c:1856:struct replay_tx_hash
**BROKEN** lightningd:     lightningd/lightningd.c:112:struct lightningd
```

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-11-17 14:09:10 +10:30
Rusty Russell
7ed2126ee7 pytest: fix flake in test_fetchinvoice_disconnected_reply.
Fails when l3 doesn't know address for l1, to connect to it:

```
2024-11-16T04:45:42.2243366Z lightningd-3 2024-11-16T04:35:10.582Z DEBUG   022d223620a359a47ff7f7ac447c85c46c923da53389221a0054c11c1e3ca31d59-connectd: peer_in WIRE_ONION_MESSAGE
2024-11-16T04:45:42.2244342Z lightningd-3 2024-11-16T04:35:10.582Z DEBUG   lightningd: Got onionmsg reply_path
2024-11-16T04:45:42.2245398Z lightningd-3 2024-11-16T04:35:10.582Z DEBUG   plugin-offers: Note: disallowing deprecated onion_message_recv.blinding
2024-11-16T04:45:42.2246408Z lightningd-3 2024-11-16T04:35:10.586Z UNUSUAL plugin-offers: No incoming channel for 5msat, so no blinded path
2024-11-16T04:45:42.2247289Z lightningd-3 2024-11-16T04:35:10.605Z DEBUG   hsmd: Client: Received message 25 from client
2024-11-16T04:45:42.2248372Z lightningd-3 2024-11-16T04:35:10.606Z DEBUG   plugin-offers: connecting directly to 0266e4598d1d3c415f572a8488830b60f7e744ed9235eb0b1ba93283b315c03518
2024-11-16T04:45:42.2249451Z lightningd-3 2024-11-16T04:35:10.606Z DEBUG   gossipd: REPLY WIRE_GOSSIPD_GET_ADDRS_REPLY with 0 fds
2024-11-16T04:45:42.2250743Z lightningd-3 2024-11-16T04:35:10.607Z DEBUG   0266e4598d1d3c415f572a8488830b60f7e744ed9235eb0b1ba93283b315c03518-connectd: Failed connected out: Unable to connect, no address known for peer
```

This is because the test which was supposed to wait for addresses is
wrong: it passes when l3 knows nothing!  (`all([])` == `True`)

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-11-17 14:09:10 +10:30
Rusty Russell
9af01b062c pytest: fix hsmtool which reports leak under address sanitizer.
Couldn't figure out why hsmtool.proc.wait(WAIT_TIMEOUT) returns 1?
hsmtool doesn't ever seem to exit status 1!

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-11-17 14:09:10 +10:30
Rusty Russell
0741d4dea1 pytest: fix flake in test_grpc_connect_notification
Looking at the logs (and comparing a successful run), it seems the connect happens before
the connect_stream is ready, so we miss it:

```
________________________ test_grpc_connect_notification ________________________
[gw7] linux -- Python 3.8.18 /home/runner/.cache/pypoetry/virtualenvs/cln-meta-project-AqJ9wMix-py3.8/bin/python

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

    def test_grpc_connect_notification(node_factory):
        l1, l2 = node_factory.get_nodes(2)
    
        # Test the connect notification
        connect_stream = l1.grpc.SubscribeConnect(clnpb.StreamConnectRequest())
        l2.connect(l1)
    
>       for connect_event in connect_stream:

tests/test_cln_rs.py:425: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
../../../.cache/pypoetry/virtualenvs/cln-meta-project-AqJ9wMix-py3.8/lib/python3.8/site-packages/grpc/_channel.py:543: in __next__
    return self._next()
../../../.cache/pypoetry/virtualenvs/cln-meta-project-AqJ9wMix-py3.8/lib/python3.8/site-packages/grpc/_channel.py:960: in _next
    _common.wait(self._state.condition.wait, _response_ready)
../../../.cache/pypoetry/virtualenvs/cln-meta-project-AqJ9wMix-py3.8/lib/python3.8/site-packages/grpc/_common.py:156: in wait
    _wait_once(wait_fn, MAXIMUM_WAIT_TIMEOUT, spin_cb)
../../../.cache/pypoetry/virtualenvs/cln-meta-project-AqJ9wMix-py3.8/lib/python3.8/site-packages/grpc/_common.py:116: in _wait_once
    wait_fn(timeout=timeout)
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <Condition(<unlocked _thread.RLock object owner=0 count=0 at 0x7fb089730f00>, 0)>
timeout = 0.1

    def wait(self, timeout=None):
        """Wait until notified or until a timeout occurs.
    
        If the calling thread has not acquired the lock when this method is
        called, a RuntimeError is raised.
    
        This method releases the underlying lock, and then blocks until it is
        awakened by a notify() or notify_all() call for the same condition
        variable in another thread, or until the optional timeout occurs. Once
        awakened or timed out, it re-acquires the lock and returns.
    
        When the timeout argument is present and not None, it should be a
        floating point number specifying a timeout for the operation in seconds
        (or fractions thereof).
    
        When the underlying lock is an RLock, it is not released using its
        release() method, since this may not actually unlock the lock when it
        was acquired multiple times recursively. Instead, an internal interface
        of the RLock class is used, which really unlocks it even when it has
        been recursively acquired several times. Another internal interface is
        then used to restore the recursion level when the lock is reacquired.
    
        """
        if not self._is_owned():
            raise RuntimeError("cannot wait on un-acquired lock")
        waiter = _allocate_lock()
        waiter.acquire()
        self._waiters.append(waiter)
        saved_state = self._release_save()
        gotit = False
        try:    # restore state no matter what (e.g., KeyboardInterrupt)
            if timeout is None:
                waiter.acquire()
                gotit = True
            else:
                if timeout > 0:
>                   gotit = waiter.acquire(True, timeout)
E                   Failed: Timeout >1200.0s
```

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-11-17 14:09:10 +10:30
Rusty Russell
bd0b8e960e pytest: fix flake in test_htlc_in_timeout
Since wait_for_onchaind_tx doesn't actually wait for the call to bitcoind to
return, we have a race in checking if the txid is in the mempool.  Fix this
by making wait_for_onchaind_tx actually wait for the response (except for delayed txs!).

```
2024-11-15T07:15:22.0836959Z     def test_htlc_in_timeout(node_factory, bitcoind, executor):
2024-11-15T07:15:22.0837722Z         """Test that we drop onchain if the peer doesn't accept fulfilled HTLC"""
2024-11-15T07:15:22.0838208Z     
2024-11-15T07:15:22.0838585Z         # HTLC 1->2, 1 fails after 2 has sent committed the fulfill
2024-11-15T07:15:22.0839137Z         disconnects = ['-WIRE_REVOKE_AND_ACK*2']
2024-11-15T07:15:22.0839741Z         # Feerates identical so we don't get gratuitous commit to update them
2024-11-15T07:15:22.0840304Z         l1 = node_factory.get_node(disconnect=disconnects,
2024-11-15T07:15:22.0840839Z                                    options={'dev-no-reconnect': None},
2024-11-15T07:15:22.0841285Z                                    feerates=(7500, 7500, 7500, 7500))
2024-11-15T07:15:22.0841673Z         l2 = node_factory.get_node()
2024-11-15T07:15:22.0842278Z         # Give it some sats for anchor spend!
2024-11-15T07:15:22.0842679Z         l2.fundwallet(25000, mine_block=False)
2024-11-15T07:15:22.0843013Z     
2024-11-15T07:15:22.0843342Z         l1.rpc.connect(l2.info['id'], 'localhost', l2.port)
2024-11-15T07:15:22.0843753Z         chanid, _ = l1.fundchannel(l2, 10**6)
2024-11-15T07:15:22.0844058Z     
2024-11-15T07:15:22.0844291Z         sync_blockheight(bitcoind, [l1, l2])
2024-11-15T07:15:22.0844606Z     
2024-11-15T07:15:22.0844958Z         amt = 200000000
2024-11-15T07:15:22.0845713Z         inv = l2.rpc.invoice(amt, 'test_htlc_in_timeout', 'desc')['bolt11']
2024-11-15T07:15:22.0846612Z         assert only_one(l2.rpc.listinvoices('test_htlc_in_timeout')['invoices'])['status'] == 'unpaid'
2024-11-15T07:15:22.0847141Z     
2024-11-15T07:15:22.0847430Z         executor.submit(l1.dev_pay, inv, dev_use_shadow=False)
2024-11-15T07:15:22.0847805Z     
2024-11-15T07:15:22.0848041Z         # l1 will disconnect and not reconnect.
2024-11-15T07:15:22.0848660Z         l1.daemon.wait_for_log('dev_disconnect: -WIRE_REVOKE_AND_ACK')
2024-11-15T07:15:22.0850393Z     
2024-11-15T07:15:22.0851297Z         # Deadline HTLC expiry minus 1/2 cltv-expiry delta (rounded up) (== cltv - 3).  cltv is 5+1.
2024-11-15T07:15:22.0852146Z         # shadow route can add extra blocks!
2024-11-15T07:15:22.0852622Z         status = only_one(l1.rpc.call('paystatus')['pay'])
2024-11-15T07:15:22.0853044Z         if 'shadow' in status:
2024-11-15T07:15:22.0853861Z             shadowlen = 6 * status['shadow'].count('Added 6 cltv delay for shadow')
2024-11-15T07:15:22.0854325Z         else:
2024-11-15T07:15:22.0854547Z             shadowlen = 0
2024-11-15T07:15:22.0854845Z         bitcoind.generate_block(2 + shadowlen)
2024-11-15T07:15:22.0855292Z         assert not l2.daemon.is_in_log('hit deadline')
2024-11-15T07:15:22.0855669Z         bitcoind.generate_block(1)
2024-11-15T07:15:22.0855950Z     
2024-11-15T07:15:22.0856406Z         l2.daemon.wait_for_log('Fulfilled HTLC 0 SENT_REMOVE_COMMIT cltv .* hit deadline')
2024-11-15T07:15:22.0856997Z         l2.daemon.wait_for_log('sendrawtx exit 0')
2024-11-15T07:15:22.0857360Z         l2.bitcoin.generate_block(1)
2024-11-15T07:15:22.0857741Z         l2.daemon.wait_for_log(' to ONCHAIN')
2024-11-15T07:15:22.0858137Z         l1.daemon.wait_for_log(' to ONCHAIN')
2024-11-15T07:15:22.0858644Z     
2024-11-15T07:15:22.0859068Z         # L2 will collect HTLC (iff no shadow route)
2024-11-15T07:15:22.0859741Z         _, txid, blocks = l2.wait_for_onchaind_tx('OUR_HTLC_SUCCESS_TX',
2024-11-15T07:15:22.0860287Z                                                   'OUR_UNILATERAL/THEIR_HTLC')
2024-11-15T07:15:22.0860662Z         assert blocks == 0
2024-11-15T07:15:22.0860908Z     
2024-11-15T07:15:22.0861262Z         # If we try to reuse the same output as we used for the anchor spend, then
2024-11-15T07:15:22.0861951Z         # bitcoind can reject it.  In that case we'll try again after we get change
2024-11-15T07:15:22.0862433Z         # from anchor spend.
2024-11-15T07:15:22.0862768Z         if txid not in bitcoind.rpc.getrawmempool():
2024-11-15T07:15:22.0863354Z             bitcoind.generate_block(1)
2024-11-15T07:15:22.0863735Z >           bitcoind.generate_block(1, wait_for_mempool=1)
2024-11-15T07:15:22.0864019Z 
```

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-11-17 14:09:10 +10:30
Rusty Russell
cac20129c6 lightningd: don't crash if replaying blocks for onchaind during shutdown.
```
lightningd-1 2024-11-15T04:06:47.660Z UNUSUAL lightningd: JSON-RPC shutdown
lightningd-1 2024-11-15T04:06:47.665Z DEBUG   lightningd: io_break: start_json_stream
lightningd-1 2024-11-15T04:06:47.666Z DEBUG   lightningd: io_loop_with_timers: main
lightningd-1 2024-11-15T04:06:47.672Z DEBUG   connectd: REPLY WIRE_CONNECTD_START_SHUTDOWN_REPLY with 0 fds
lightningd-1 2024-11-15T04:06:47.674Z DEBUG   lightningd: io_break: connectd_start_shutdown_reply
lightningd-1 2024-11-15T04:06:47.680Z DEBUG   022d223620a359a47ff7f7ac447c85c46c923da53389221a0054c11c1e3ca31d59-onchaind-chan#1: Status closed, but not exited. Killing
lightningd-1 2024-11-15T04:06:47.715Z **BROKEN** lightningd: FATAL SIGNAL 11 (version e627dbf-modded)
------------------------------- Valgrind errors --------------------------------
Valgrind error file: valgrind-errors.43310
==43310== Invalid read of size 8
==43310==    at 0x1B5717: subd_send_msg (subd.c:842)
==43310==    by 0x17563A: onchain_tx_depth (onchain_control.c:177)
==43310==    by 0x175E92: replay_block (onchain_control.c:391)
==43310==    by 0x12E30C: getrawblockbyheight_callback (bitcoind.c:506)
==43310==    by 0x1A5AC0: plugin_response_handle (plugin.c:663)
==43310==    by 0x1A5D3C: plugin_read_json_one (plugin.c:775)
==43310==    by 0x1A5F79: plugin_read_json (plugin.c:826)
==43310==    by 0x38F320: next_plan (io.c:60)
==43310==    by 0x38FF76: do_plan (io.c:422)
==43310==    by 0x38FFDD: io_ready (io.c:439)
==43310==    by 0x392411: io_loop (poll.c:455)
==43310==    by 0x1AB630: shutdown_plugins (plugin.c:2588)
==43310==  Address 0x58 is not stack'd, malloc'd or (recently) free'd
==43310== 
```

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-11-17 14:09:10 +10:30
Rusty Russell
102e22347d pytest: fix flake in test_wss_proxy
```
>       wss = BindWebSecureSocket('localhost', wss_port)

tests/test_connection.py:4584: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
tests/test_connection.py:4570: in __init__
    self.ws.connect("wss://" + hostname + ":" + str(port))
../../../.cache/pypoetry/virtualenvs/cln-meta-project-AqJ9wMix-py3.8/lib/python3.8/site-packages/websocket/_core.py:256: in connect
    self.sock, addrs = connect(
../../../.cache/pypoetry/virtualenvs/cln-meta-project-AqJ9wMix-py3.8/lib/python3.8/site-packages/websocket/_http.py:145: in connect
    sock = _open_socket(addrinfo_list, options.sockopt, options.timeout)
../../../.cache/pypoetry/virtualenvs/cln-meta-project-AqJ9wMix-py3.8/lib/python3.8/site-packages/websocket/_http.py:232: in _open_socket
    raise err
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

addrinfo_list = [(<AddressFamily.AF_INET6: 10>, <SocketKind.SOCK_STREAM: 1>, 6, '', ('::1', 45521, 0, 0)), (<AddressFamily.AF_INET: 2>, <SocketKind.SOCK_STREAM: 1>, 6, '', ('127.0.0.1', 45521))]
sockopt = [], timeout = None

    def _open_socket(addrinfo_list, sockopt, timeout):
        err = None
        for addrinfo in addrinfo_list:
            family, socktype, proto = addrinfo[:3]
            sock = socket.socket(family, socktype, proto)
            sock.settimeout(timeout)
            for opts in DEFAULT_SOCKET_OPTION:
                sock.setsockopt(*opts)
            for opts in sockopt:
                sock.setsockopt(*opts)
    
            address = addrinfo[4]
            err = None
            while not err:
                try:
>                   sock.connect(address)
E                   ConnectionRefusedError: [Errno 111] Connection refused
```

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-11-17 14:09:10 +10:30
Rusty Russell
40a4d83764 pytest: don't assume gossip order in test_gossip_query_channel_range
```
        # reply_channel_range == 264
>       assert msgs == ['0108'
                        # blockhash
                        + genesis_blockhash
                        # first_blocknum, number_of_blocks, complete
                        + format(0, '08x') + format(1000000, '08x') + '01'
                        # encoded_short_ids
                        + format(len(encoded) // 2, '04x')
                        + encoded]
E       AssertionError: assert ['010806226e46111a0b59caaf126043eb5bbf28c34f3a5e332a1fc7b2b73cf188910f00000000000f42400100110000006900000100000000680000010000'] == ['010806226e46111a0b59caaf126043eb5bbf28c34f3a5e332a1fc7b2b73cf188910f00000000000f42400100110000006800000100000000690000010000']
E         At index 0 diff: '010806226e46111a0b59caaf126043eb5bbf28c34f3a5e332a1fc7b2b73cf188910f00000000000f42400100110000006900000100000000680000010000' != '010806226e46111a0b59caaf126043eb5bbf28c34f3a5e332a1fc7b2b73cf188910f00000000000f42400100110000006800000100000000690000010000'
E         Full diff:
E         - ['010806226e46111a0b59caaf126043eb5bbf28c34f3a5e332a1fc7b2b73cf188910f00000000000f42400100110000006800000100000000690000010000']
E         ?                                                                                                    ^               ^
E         + ['010806226e46111a0b59caaf126043eb5bbf28c34f3a5e332a1fc7b2b73cf188910f00000000000f42400100110000006900000100000000680000010000']
E         ?                                                                                                    ^               ^
```

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-11-17 14:09:10 +10:30
Rusty Russell
a5ba3f8f24 pytest: reduce askrene tests again for CI.
```
2024-11-14T23:50:43.8609029Z test_real_data failed (1 runs remaining out of 2).
2024-11-14T23:50:43.8609157Z 	<class 'Failed'>
2024-11-14T23:50:43.8609244Z 	Timeout >1200.0s
...
2024-11-14T23:50:43.8629292Z test_real_biases failed (1 runs remaining out of 2).
2024-11-14T23:50:43.8629407Z 	<class 'Failed'>
2024-11-14T23:50:43.8629494Z 	Timeout >1200.0s
```

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-11-17 14:09:10 +10:30
Rusty Russell
dd569b0b7a pytest: disable broken test
Seems like it's using an old version of pyln-client, which had the bug
of referring to long_desc:

```
def test_local_dir_install(node_factory):
        """Test search and install from local directory source."""
        n = get_reckless_node(node_factory)
        n.start()
        r = reckless([f"--network={NETWORK}", "-v", "source", "add",
                      "tests/data/recklessrepo/lightningd/testplugpass"],
                     dir=n.lightning_dir)
        assert r.returncode == 0
        r = reckless([f"--network={NETWORK}", "-v", "install", "testplugpass"], dir=n.lightning_dir)
        assert r.returncode == 0
>       assert 'testplugpass enabled' in r.stdout
E       assert 'testplugpass enabled' in '[2024-11-14 06:47:12,999] DEBUG: Searching for testplugpass\nfound testplugpass in source: tests/data/recklessrepo/lightningd/testplugpass\n[2024-11-14 06:47:13,031] DEBUG: entry: testplugpass.py\n[2024-11-14 06:47:13,031] DEBUG: Retrieving testplugpass from tests/data/recklessrepo/lightningd/testplugpass\n[2024-11-14 06:47:13,032] DEBUG: Install requested from InstInfo(testplugpass, tests/data/recklessrepo/lightningd/testplugpass, None, testplugpass.py, requirements.txt, None).\n[2024-11-14 06:47:13,032] DEBUG: copying local directory contents from tests/data/recklessrepo/lightningd/testplugpass\n[2024-11-14 06:47:13,038] DEBUG: cloned_src: InstInfo(testplugpass, /tmp/reckless-0721411112afw6ng7/clone, None, testplugpass.py, requirements.txt, testplugpass)\n[2024-11-14 06:47:13,038] DEBUG: using installer python3venv\n[2024-11-14 06:47:13,038] DEBUG: creating /tmp/ltests-chy6ayqu/test_local_dir_install_2/lightning-1/reckless/testplugpass\n[2024-11-14 06:47:13,038] DEBUG: creating /tmp/ltests-chy6ayqu/test_local_dir_install_2/lightning-1/reckless/testplugpass/source\n[2024-11-14 06:47:13,038] DEBUG: copying /tmp/reckless-0721411112afw6ng7/clone/testplugpass tree to /tmp/ltests-chy6ayqu/test_local_dir_install_2/lightning-1/reckless/testplugpass/source/testplugpass\n[2024-11-14 06:47:13,039] DEBUG: linking source /tmp/ltests-chy6ayqu/test_local_dir_install_2/lightning-1/reckless/testplugpass/source/testplugpass/testplugpass.py to /tmp/ltests-chy6ayqu/test_local_dir_install_2/lightning-1/reckless/testplugpass/testplugpass.py\n[2024-11-14 06:47:13,039] DEBUG: InstInfo(testplugpass, /tmp/ltests-chy6ayqu/test_local_dir_install_2/lightning-1/reckless/testplugpass, None, testplugpass.py, requirements.txt, source/testplugpass)\n[2024-11-14 06:47:20,508] DEBUG: configuring a python virtual environment (pip) in /tmp/ltests-chy6ayqu/test_local_dir_install_2/lightning-1/reckless/testplugpass/.venv\n[2024-11-14 06:47:20,508] DEBUG: virtual environment created in /tmp/ltests-chy6ayqu/test_local_dir_install_2/lightning-1/reckless/testplugpass/.venv.\nCollecting pyln-client\n  Using cached pyln_client-24.8.2-py3-none-any.whl (35 kB)\nCollecting pyln-proto>=23\n  Using cached pyln_proto-24.8.2-py3-none-any.whl (31 kB)\nCollecting pyln-bolt7>=1.0\n  Using cached pyln_bolt7-1.0.246-py3-none-any.whl (18 kB)\nCollecting base58<3.0.0,>=2.1.1\n  Using cached base58-2.1.1-py3-none-any.whl (5.6 kB)\nCollecting cryptography<43,>=42\n  Using cached cryptography-42.0.8-cp37-abi3-manylinux_2_28_x86_64.whl (3.9 MB)\nCollecting bitstring<5.0.0,>=4.1.0\n  Using cached bitstring-4.2.3-py3-none-any.whl (71 kB)\nCollecting coincurve<21,>=20\n  Using cached coincurve-20.0.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (1.2 MB)\nCollecting PySocks<2,>=1\n  Using cached PySocks-1.7.1-py3-none-any.whl (16 kB)\nCollecting bitarray<3.0.0,>=2.9.0\n  Using cached bitarray-2.9.3-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (288 kB)\nCollecting cffi>=1.3.0\n  Using cached cffi-1.17.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (446 kB)\nCollecting asn1crypto\n  Using cached asn1crypto-1.5.1-py2.py3-none-any.whl (105 kB)\nCollecting pycparser\n  Using cached pycparser-2.22-py3-none-any.whl (117 kB)\nInstalling collected packages: bitarray, asn1crypto, PySocks, pyln-bolt7, pycparser, bitstring, base58, cffi, cryptography, coincurve, pyln-proto, pyln-client\nSuccessfully installed PySocks-1.7.1 asn1crypto-1.5.1 base58-2.1.1 bitarray-2.9.3 bitstring-4.2.3 cffi-1.17.1 coincurve-20.0.0 cryptography-42.0.8 pycparser-2.22 pyln-bolt7-1.0.246 pyln-client-24.8.2 pyln-proto-24.8.2\ndependencies installed successfully\n[2024-11-14 06:47:37,424] DEBUG: virtual environment for cloned plugin: .venv\n[2024-11-14 06:47:37,746] DEBUG: plugin testing error:\n[2024-11-14 06:47:37,746] DEBUG:   Traceback (most recent call last):\n[2024-11-14 06:47:37,746] DEBUG:     File "/tmp/ltests-chy6ayqu/test_local_dir_install_2/lightning-1/reckless/testplugpass/testplugpass.py", line 9, in <module>\n[2024-11-14 06:47:37,746] DEBUG:       runpy.run_module("testplugpass", {}, "__main__")\n[2024-11-14 06:47:37,746] DEBUG:     File "/opt/hostedtoolcache/Python/3.8.18/x64/lib/python3.8/runpy.py", line 210, in run_module\n[2024-11-14 06:47:37,746] DEBUG:       return _run_code(code, {}, init_globals, run_name, mod_spec)\n[2024-11-14 06:47:37,746] DEBUG:     File "/opt/hostedtoolcache/Python/3.8.18/x64/lib/python3.8/runpy.py", line 87, in _run_code\n[2024-11-14 06:47:37,746] DEBUG:       exec(code, run_globals)\n[2024-11-14 06:47:37,746] DEBUG:     File "/tmp/ltests-chy6ayqu/test_local_dir_install_2/lightning-1/reckless/testplugpass/source/testplugpass/testplugpass.py", line 25, in <module>\n[2024-11-14 06:47:37,746] DEBUG:       plugin.run()\n[2024-11-14 06:47:37,746] DEBUG:     File "/tmp/ltests-chy6ayqu/test_local_dir_install_2/lightning-1/reckless/testplugpass/.venv/lib/python3.8/site-packages/pyln/client/plugin.py", line 877, in run\n[2024-11-14 06:47:37,747] DEBUG:       return self.print_usage()\n[2024-11-14 06:47:37,747] DEBUG:     File "/tmp/ltests-chy6ayqu/test_local_dir_install_2/lightning-1/reckless/testplugpass/.venv/lib/python3.8/site-packages/pyln/client/plugin.py", line 831, in print_usage\n[2024-11-14 06:47:37,747] DEBUG:       doc = method.long_desc if method.long_desc is not None else "No documentation found"\n[2024-11-14 06:47:37,747] DEBUG:   AttributeError: \'Method\' object has no attribute \'long_desc\'\n[2024-11-14 06:47:37,747] ERROR: plugin testing failed\n[2024-11-14 06:47:37,937] WARNING: testplugpass: installation aborted\n'
```

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-11-17 14:09:10 +10:30
Rusty Russell
44f63a360b build: fix race where channeld_fakenet doesn't depend on external modules.
Because it wasn't in ALL_OBJS.  Copy the Makefile pattern!

```
Submodule 'src/secp256k1' (https://github.com/ElementsProject/secp256k1-zkp.git) registered for path 'external/libwally-core/src/secp256k1'
Cloning into '/home/runner/work/lightning/lightning/external/libwally-core/src/secp256k1'...
cc tests/plugins/channeld_fakenet.c
In file included from ./bitcoin/script.h:4,
                 from tests/plugins/channeld_fakenet.c:14:
./bitcoin/signature.h:6:10: fatal error: secp256k1.h: No such file or directory
    6 | #include <secp256k1.h>
      |          ^~~~~~~~~~~~~
compilation terminated.
make: *** [Makefile:301: tests/plugins/channeld_fakenet.o] Error 1
make: *** Waiting for unfinished jobs....
Submodule path 'external/libwally-core/src/secp256k1': checked out
```

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-11-17 14:09:10 +10:30
Rusty Russell
4f4bf7730e pytest: fix test_onchain_unwatch under valgrind.
valgrind slowed things down so the HTLC was resolved, so we didn't use
an anchor.  Make that case consistent.

```
    def test_onchain_unwatch(node_factory, bitcoind, chainparams):
        """Onchaind should not watch random spends"""
        # We track channel balances, to verify that accounting is ok.
        coin_mvt_plugin = os.path.join(os.getcwd(), 'tests/plugins/coin_movements.py')
        l1, l2 = node_factory.line_graph(2, opts={'plugin': coin_mvt_plugin})
        channel_id = first_channel_id(l1, l2)
    
        l1.pay(l2, 200000000)
    
        l1.rpc.dev_fail(l2.info['id'])
        l1.daemon.wait_for_log('Failing due to dev-fail command')
        l1.wait_for_channel_onchain(l2.info['id'])
    
        # Make sure we see anchor too
>       l1.bitcoin.generate_block(1, wait_for_mempool=2)

tests/test_closing.py:1769: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
contrib/pyln-testing/pyln/testing/utils.py:477: in generate_block
    wait_for(lambda: len(self.rpc.getrawmempool()) >= wait_for_mempool)
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

success = <function BitcoinD.generate_block.<locals>.<lambda> at 0x7f23f909c310>
timeout = 180

    def wait_for(success, timeout=TIMEOUT):
        start_time = time.time()
        interval = 0.25
        while not success():
            time_left = start_time + timeout - time.time()
            if time_left <= 0:
>               raise ValueError("Timeout while waiting for {}".format(success))
E               ValueError: Timeout while waiting for <function BitcoinD.generate_block.<locals>.<lambda> at 0x7f23f909c310>
```

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-11-17 14:09:10 +10:30
Rusty Russell
4f5865167e pytest: fix spurious error in test_important_plugin
```
**BROKEN** plugin-spenderp: Lost connection to the RPC socket.
```

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-11-17 14:09:10 +10:30
Rusty Russell
ecc3a00839 pytest: don't try exposesecret test under valgrind.
There's a known issue with hsm passwords and valgrind:

```
        write_all(master_fd, (password + '\n').encode("utf-8"))
>       l1.daemon.wait_for_log("Server started with public key")

tests/test_plugin.py:4526: 
...
                        if self.is_in_log(r):
                            print("({} was previously in logs!)".format(r))
>                   raise TimeoutError('Unable to find "{}" in logs.'.format(exs))
E                   TimeoutError: Unable to find "[re.compile('Server started with public key')]" in logs.
```

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-11-17 14:09:10 +10:30
Dusty Daemon
3ef52d3001 Update Mac install instructions
Rust needs ‘protobuf’ installed.

Changelog-None
2024-11-17 11:19:38 +10:30
arowser
48a24cd51b closingd: Fix buffer overread build error with some cross build 2024-11-17 11:00:49 +10:30
Dusty Daemon
9708ee3166 secp256k1 pubkey constant fix
Spotted a number being used instead of the macro constant.

Changelog-None
2024-11-17 10:55:28 +10:30
niftynei
e66653fa1d hsmtool: fixup show usage parens + return 2024-11-15 12:48:44 +10:30
bstin
fb65ec9063 lightning-hsmtool.8.md: Update documentation showing new method
[ Modified to extend generatehsm --RR ]
2024-11-15 12:48:44 +10:30
Rusty Russell
b7d77b49df hsmtool.c: extend generatehsm to allow command-line args.
Based on the patch by bstin <barry.github@capsmx.com>, which added a separate command,
this simply extends "generatehsm" to allow more options.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
Changelog-Added: hsmtool: generatehsm can run non-interactive, taking options on the cmdline.
2024-11-15 12:48:44 +10:30
Jesse de Wit
087a29b0b3 libplugin-pay: trace payment_continue
Changelog-Added: Plugins: `pay` now has tracing support for various payment steps.
2024-11-13 13:15:52 +01:00
Jesse de Wit
2c09f9ddf0 trace: trim quotes from tag values 2024-11-13 13:15:52 +01:00
Christian Decker
f36be4b006 plugin: Add tracing support for send_outreq
The `send_outreq` function is a good place to suspend and resume
traces, since these are usually the places where we hand off control
back to the `io_loop`. This assumes that we do not continue doing
heavy liftin after we have queued an `outreq` call, but that is most
likely the case anyway. This frees us from having to track suspensions
whenever we call the RPC from a plugin.
2024-11-13 13:15:52 +01:00
Rusty Russell
d57accfca7 lightningd: wait for onchaind to ack new spends before continuing replay.
Christian noted that if we don't do this we could flood onchaind with messages:
particularly in Greenlight where the HSM (remote) may delay indefinitely, so
onchaind doesn't process messages.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-11-13 14:44:03 +10:30
Rusty Russell
0dc1c5a061 onchaind: explicit ack for onchaind_spent method.
This means it always tells us explicitly whether to keep watching or not,
and we know it's processed it.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-11-13 14:44:03 +10:30
Rusty Russell
77fdd63c50 lightningd: allow subd_req() to take replycb_data arg.
Useful if it's only to be used for the duration of the callback.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-11-13 14:44:03 +10:30
Rusty Russell
658cc9db5f gossipd: replay old spent UTXOs when restarting.
This may help the cases we see where gossipd doesn't realize channels
are closed (because of shutdown before it processed the closing).

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
Changelog-Fixed: `gossipd` will no longer miss some channel closes on restart.
2024-11-13 14:44:03 +10:30
Rusty Russell
a4847b5af4 lightningd: only trim old UTXO entries after gossipd acks block.
If it gets really far behind, then we restart, it could miss some.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-11-13 14:44:03 +10:30
Rusty Russell
20a41fd798 lightningd: only store channel funding spend txs into db.
Now we do replay, we don't need the others.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-11-13 14:44:03 +10:30
Rusty Russell
5c81b0c3dc lightningd: use block-at-a-time replay for onchaind on restart.
And we hook in the replay watch code.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
Changelog-Fixed: `onchaind` can miss conclusion of final txs in some cases, will now replay independently.
2024-11-13 14:44:03 +10:30
Rusty Russell
b098ff03a5 lightningd: separate code for onchaind watches separate if we're doing replay.
We start by telling onchaind about the funding spend, and anything
which spends it, and it tells us the txids it *doesn't* want to watch
any more.  We're going to use a separate set of watches for the replay
case: this implements that code.

Once we're caught up, we convert any remaining watches to normal ones
to follow future blocks.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-11-13 14:44:03 +10:30
Rusty Russell
f7f3ebae32 wallet: new routine to simply get the funding spend tx, if known.
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-11-13 14:44:03 +10:30
Rusty Russell
3ad7167cfa fuzz: fix up compilation with hsmtool change.
```
tests/fuzz/fuzz-hsm_encryption.c:28:80: error: passing 'char **' to parameter of type 'const char **' discards qualifiers in nested pointer types [-Werror,-Wincompatible-pointer-types-discards-qualifiers]
                assert(!hsm_secret_encryption_key_with_exitcode(passphrase, &encryption_key, &emsg));
                                                                                             ^~~~~
```

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-11-13 13:24:06 +10:30
Rusty Russell
d3ad68c647 pytest: reduce time for askrene test_real_data test.
Timing out under CI (1800 seconds!)

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-11-13 13:24:06 +10:30
Rusty Russell
c31b57c32a plugins/exposesecret: fix for API change.
That will teach me to merge without rebasing.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-11-13 13:24:06 +10:30
Rusty Russell
8293352425 config: add the ability for plugins to specify that config values should be concealed.
And use it for `exposesecret-passphrase`.  This is probably overly
cautious, but it makes me feel a little better that we won't leak it
to someone with read-only access.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-11-13 08:49:55 +10:30
Rusty Russell
101aeea52c ccan: update to latest version
Gives us more room for user bits in opt.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-11-13 08:49:55 +10:30
Rusty Russell
e261301301 exposesecret: new plugin and command to get hsm_secret.
Being able to back up the hsm_secret is critical, but you cannot do
this through a UI, because of course we do not allow such access.
People have lost funds because they didn't back up.

This allows access to the hsm_secret if you use a password set in the
config file.  (If it's not set, the command does not work).  This is a
compromise, of course.

Changelog-Added: `exposesecret` command for encouraging hsm_secret backups.
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-11-13 08:49:55 +10:30
Rusty Russell
ab6f405ae7 common/hsm_encryption: use const char * for errors.
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-11-13 08:49:55 +10:30
Lagrang3
bc419b41a8 lightningd: add option dev-strict-forwarding
Changelog-Add: add option dev-strict-forwarding
2024-11-12 10:44:10 +01:00
Rusty Russell
fcdbbd8534 doc: improve documentation of listpays
1. It's called listpays not listpay.
2. "index" does NOT have a default value (it must be specified if limit or start are used)
3. Note that limit and start have effects on accuracy, since we combine records.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-11-12 10:43:37 +01:00
daywalker90
c4e67c0b96 add listing options to listpays
Changelog-Added: JSON-RPC: `listpays` has `index`, `start` and `limit` parameters for listing control.
2024-11-12 10:43:37 +01:00
Rusty Russell
ccd9b21d04 autoclean: rest between cleanup calls.
This means we don't consume *all* the CPU.

Changelog-Fixed: Plugins: `autoclean` is now gentler on the node when doing giant cleans.
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-11-12 10:42:18 +01:00
Rusty Russell
49380239e9 autoclean: don't slam lightningd with 10,000 requests at once.
On a large node, especially with postgres, this causes every other command
to take 30 seconds plus.  The first, obvious, step is to reduce how many
commands we will do at once.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-11-12 10:42:18 +01:00
Rusty Russell
b34adc704b pyln-testing: don't fail to start node if we have no Rust.
No cln-grpc means no "grpc-port" option!  I often test this way, with RUST=0
for speed.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-11-12 09:56:39 +01:00
evansmj
edc0eb6473 bkpr: add examples for new edit description RPC calls 2024-11-12 09:46:09 +10:30
niftynei
7b8d484684 bkpr: add tests for new edit description RPC calls
Lets make sure that edit description works as intended.
2024-11-12 09:46:09 +10:30
niftynei
2b4b91ff5c bkpr: add new RPC bkpr-editdescriptionbyoutpoint
Given an {outpoint}, sets the description on the matching outpoint (if exists).

Note that if no outpoint exists in bookkeeper, will return an empty list

Changleog-Added: PLUGINS: bookkeeper has a new RPC `bkrp-editdescriptionbyoutpoint` which will set/update a description for an outpoint creation event.
2024-11-12 09:46:09 +10:30
niftynei
a61b7ef347 bkpr: add new json RPC "bkpr-editdescriptionbypaymentid"
This takes an {payment_id} and {description}.
It looks for all chain + channel events that match
that {payment_id} and updates the description for those events.

We return all the updated events. If no events are updated, an empty
list is returned.

Changelog-Added: PLUGINS: bookkeeper has a new RPC `bkpr-editdescriptionbypaymentid` which will update the description for any event with matching payment_id
2024-11-12 09:46:09 +10:30
niftynei
4a6e014213 bkpr: refactor out the add_events logic for json stuff 2024-11-12 09:46:09 +10:30
jackstar12
64b7b98f59 doc: add grpc-host and default grpc-port 2024-11-12 09:43:54 +10:30
jackstar12
0b5944708e tests: adjust cln-grpc tests for new default start 2024-11-12 09:43:54 +10:30
jackstar12
bc9834c459 plugins/grpc: grpc-host option
A port should not be opened by default on 0.0.0.0, so change the default
to localhost

Changelog-Added: `grpc-host` option for grpc plugin
2024-11-12 09:43:54 +10:30
jackstar12
1b4e3fff89 plugins/grpc: default value for grpc port
Changelog-Changed: grpc now starts on port 9736 by default
2024-11-12 09:43:54 +10:30
Dusty Daemon
dd956e2210 splice: reestablish should only assume stfu in one case 2024-11-12 06:42:52 +10:30
Dusty Daemon
fe7ba77234 splice: Add more verbose reestablish debug logging 2024-11-12 06:42:52 +10:30
Dusty Daemon
475d5f8bf9 splice: Abort on insufficent funds
If the user does not supply enough funds treat it as an abort instead of a channel warning.

Also clean up some indentation while we’re there.
2024-11-12 06:42:52 +10:30
Dusty Daemon
14b63d8927 splice: Add test of “splice” script command
Tests that splice-in and splice-out work through the scripting process and confirm the resulting balances are correct.
2024-11-12 06:42:52 +10:30
Dusty Daemon
e4978a4037 splice: Update splice fee maximums
The fee maximum is used to issue a warning to the user their feerate is high in case they accidentally make a large donation to miners.

During python testing the feerates are high on purpose so we raise the warning level to at least the penality feerate.
2024-11-12 06:42:52 +10:30
Dusty Daemon
eb83ab15ae peer_control: Don’t report removed inflights 2024-11-12 06:42:52 +10:30
Dusty Daemon
5b211c0389 splice: Documentation for the “splice” command
Adding schema and documentatino for how to use the scripting portion of the “splice” RPC command.
2024-11-12 06:42:52 +10:30
Dusty Daemon
7fd16dc493 splice: Add plugin for magic “splice all” command
The command called “splice” can take a json payload or a ‘splice script’, process it into a list of ‘actions’ and then execute those actions.

These actions include or will include everything you would want to do with a splice:
* Splice into a channel
* Splice out of a channel
* Fund from wallet
* Deposit to wallet
* Send funds to bitcoin address

Changelog-Added: A new magic “splice” command is added that can take a ‘splice script’ or json payload and perform any complex splice across multiple channels merging the result into a single transaction. Some features are disabled and will be added in time.
2024-11-12 06:42:52 +10:30
Dusty Daemon
7ce0dc6e2e addpsbtoutput: Add serial_id flag
When set this flag tells addpsbtoutput to add the intiator serial_id to the added output.

Changelog-Changed: addpsbtoutput now allows serial_id to be set while adding which is needed for splicing and dual.
2024-11-12 06:42:52 +10:30
Dusty Daemon
8221c96eab addpsbtinput: New RPC command to add funds to a psbt
This is the sister command of addpsbtoutput.

Adds inputs equal to or greater than the amount requests, reservers them, and reports important information back out to the user.

Changelog-Added: New low-level RPC command addpsbtinput to fund PSBTs directly and help with complex splices & dual-opens.
2024-11-12 06:42:52 +10:30
Dusty Daemon
879d1191e8 splice: Bulk channel stfu and abort RPC
The ability to stfu channels in bulk is required to do complex multi channel operations. When stfu’ing in this manner, the available funds at the moment of stfu is returned to the user.

In order to cancel the stfu we also add a bulk tx_abort command.

Changelog-Added: `stfu_channels` and `abort_channels` are added for bulk multi-channel splice commands. These allow the user to pause (and resume) multiple channels in place.
2024-11-12 06:42:52 +10:30
Dusty Daemon
d60e9f342b splice: Extract remote sig from psbt if needed
On certain well timed restarts we lose their siganture from memory and don’t receive it from them. In these cases we can extract it from the PSBT directly.
2024-11-12 06:42:52 +10:30
Dusty Daemon
73ad8eaa31 splice: Allow splice_update to return signatures
This is needed to all multi-channel splices. When channeld can return the signatures to the user (based on signing order precedent), it now does from splice_update.

Additionally, we move sending of the initial psbt from splice_init down to splice_update. This is also necessary for correct psbt diff detection during multi-channel splices.

Changelog-Changed: splice_update can in some cases now return the remotely partiall signed psbt to the user, if so `signtures_secured` will be true.
2024-11-12 06:42:52 +10:30
Dusty Daemon
0d241ee187 psbt: comment typo fix 2024-11-12 06:42:52 +10:30
Dusty Daemon
b03f299c9b splice: Modify splice_signed to work with multiple channels
`splice_signed` now searchs the PSBT for channel ids

Changelog-Changed: `splice_signed` parameters are switched in order to make `channel_id` an optional parameter, enabling multi-splice-signatures.
2024-11-12 06:42:52 +10:30
Dusty Daemon
89b110d085 psbt: Add ability to set channel_ids in psbt globals
Stores an array of channel_ids into the PSBT globals area.

Changelog-None
2024-11-12 06:42:52 +10:30
Dusty Daemon
66fe338290 psbt: Add ability to set global PSBT values
Changelog-None
2024-11-12 06:42:52 +10:30
Dusty Daemon
fa0d9b6d2a psbt: Add ability to extract signature
A routine for getting a signature back out of an input’s list of pending signatures via pubkey search.

This is needed for certain kinds of restarts as we lose our peer’s signature from memory but a copy is kept in the PSBT.
2024-11-12 06:42:52 +10:30
Dusty Daemon
3c01fc240a splice: A splice-script test that tests complex corner cases
A test that puts some advanced and complex scripts into the parser and validates the results that come out.
2024-11-12 06:42:52 +10:30
Dusty Daemon
fb3e72687c splice: Script for complex splices
New compiler for splice scripts that parses splice scripts, validates them, converts them to json and back again.

Changelog-Added: Splice script parser — takes a custom splice query language to bundle multiple complex splices into a single task in a simple way.
2024-11-12 06:42:52 +10:30
Dusty Daemon
60e6f7eb48 mac: build warning about unused result
Changelog-None
2024-11-12 06:42:52 +10:30
Rusty Russell
48f50a26bf askrene: commit to API.
This does not mean it won't change, just that it will be backwards compatible.

Changelog-Added: Plugins: `askrene` which provides `getroutes` and a complete API for adding information in layers.
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-11-08 21:48:55 +10:30
Rusty Russell
d85dcc0ce4 askrene: persistent layer support.
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-11-08 21:48:55 +10:30
Rusty Russell
b2dcf7248d askrene: add askrene-bias-channel.
This lets you place annotated biases on channels, to influence routing.

Uses include avoiding TOR nodes, slow channels or other local preferences.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
Changelog-None: askrene is new anyway.
2024-11-08 21:48:55 +10:30
Rusty Russell
bd58355729 doc: add lightning-askrene-age to Makefile.
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-11-08 21:48:55 +10:30
Rusty Russell
3f09e503ec askrene: fix false positive memleak since we didn't scan local_updates.
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-11-08 21:48:55 +10:30
fanquake
23465f06df build: add all-fuzz-programs target
Add a convenience target for building, but not running (i.e check-fuzz),
all fuzz targets.

Signed-off-by: fanquake <fanquake@gmail.com>
2024-11-08 11:13:53 +01:00
Rusty Russell
bfc00bc7f2 lightningd: avoid false memleak positive with rpc_command_hook.
On `dev-memleak`, if someone is using rpc_command_hook, we'll call
it when the hook returns.  But it will see these contexts as a leak.

So attach them to tmpctx (which is excluded from leak detection).

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-11-07 17:04:35 +10:30
Rusty Russell
5681c088cf libplugin: call get_beglist async, in case they subscribe to the rpc_command hook.
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
Changelog-Fixed: libplugin: plugins can now intercept `rpc_command` hook without deadlocking.
2024-11-07 17:04:35 +10:30
Rusty Russell
c797b6fb20 libplugin: add method string to jsonrpc callbacks, implement generic helpers.
Without knowing what method was called, we can't have useful general logging
methods, so go through the pain of adding "const char *method" everywhere,
and add:

1. ignore_and_complete - we're done when jsonrpc returned
2. log_broken_and_complete - we're done, but emit BROKEN log.
3. plugin_broken_cb - if this happens, fail the plugin.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-11-07 17:04:35 +10:30
Rusty Russell
9f92af9fab libplugin: use NULL to imply "take prefix from cmd".
This avoids jsonrpc_request_start() double-evaluating its cmd arg.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-11-07 17:04:35 +10:30
Rusty Russell
4f4ec9aefd askrene: make sure we depend on libplugin.h
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-11-07 17:04:35 +10:30
Rusty Russell
c5099b1647 libplugin: clean up API.
When we used to allow cmd to be NULL, we had to hand the plugin
everywhere.  We no longer do.

1. Various jsonrpc_ functions no longer need the plugin arg.
2. send_outreq no longer needs a plugin arg.
3. The init function takes a command, not a plugin.
4. Remove command_deprecated_in_nocmd_ok.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-11-07 17:04:35 +10:30
Rusty Russell
00d851c792 libplugin: check that command has/hasn't terminated when we get pending/complete.
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-11-07 17:04:35 +10:30
Rusty Russell
6a3e9d91f9 libplugin: insist on always having a non-NULL command context.
And remove command_done() which was used when there was no
cmd.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-11-07 17:04:35 +10:30
Rusty Russell
bc22a8db4f libplugin-pay: fix command logging
We were dereferencing the first character of the id, (always '"') which meant
everything was id 34.

Before:
	plugin-pay: cmd 34 partid 5

After:
	cmd pytest:pay#62/cln:pay#105 partid 0

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
Changelog-Fixed: `pay`: debug logging now uses correct JSON ids.
2024-11-07 17:04:35 +10:30
Rusty Russell
ec8293d215 libplugin-pay: always use a non-NULL struct command.
This means we replace p->cmd with an auxillary command after we've
finished, so we have a valid command to use.

It also means we weave `struct command_result` returns back through
all the callers.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-11-07 17:04:35 +10:30
Rusty Russell
0a909bdea5 libplugin: reindent.
This does not code changes, but makes the next changes easier.

We short-cut the "we are a child" case and de-indent the main
cases.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-11-07 17:04:35 +10:30
Rusty Russell
909a9de9fd funder: use auxilliary command instead of NULL command.
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-11-07 17:04:35 +10:30
Rusty Russell
b1e2be3c89 commando: always use proper responses for commands.
All `struct command` should be terminated properly.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-11-07 17:04:35 +10:30
Rusty Russell
7ce30e2873 libplugin: make timers have a "command" context.
This is cleaner: everything can now be associated with a command
context.

You're supposed to eventually dispose of it using timer_complete().

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-11-07 17:04:35 +10:30
Rusty Russell
45f56f8e5d libplugin: enumerate the specific "struct command" types.
This is clearer than the previous "two booleans".

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-11-07 17:04:35 +10:30
Rusty Russell
7fe7f49ecf libplugin: always set the "id" field of a command.
We didn't set this previously when it was a notification.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-11-07 17:04:35 +10:30
Rusty Russell
606aab6f55 libplugin: add aux_command.
Sometimes we want to clean up *after* a command has completed, but
we're moving to a model where all libplugin operations require a
`struct command`.  This adds `aux_command` to create an
independent-lifetime command with the same id.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-11-07 17:04:35 +10:30
Rusty Russell
c85dd95c12 libplugin: tell compiler that plugin_err is like printf.
And fix the fallout!

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-11-07 17:04:35 +10:30
Rusty Russell
6303a96ee2 devtools/gossmap-compress: make fake nodeids same for 32/64 bits.
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-11-06 21:17:36 +10:30
Rusty Russell
8c06d0d410 channeld_fakenet: remove HTLCs after completion.
I started getting "WIRE_TEMPORARY_CHANNEL_FAILURE: Too many HTLCs" after
two hundred xpay attempts.

This was nice (it found some bugs in injectpaymentonion's handling of
local errors, and in xpay's reporting), but shouldn't happen.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-11-06 21:17:36 +10:30
Rusty Russell
257e41ebe6 channeld_fakenet: add capacity information.
Start with a random capacity (linear prob), and remember in-progess
payments so we can simulate them using capacity properly.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-11-06 21:17:36 +10:30
Rusty Russell
b2a9edf49d channeld_fakenet: add deterministic delays.
100ms to 1 second per hop.  We don't do delays on the way back though!

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-11-06 21:17:36 +10:30
Rusty Russell
4b23ffa6f2 pytest: test askrene and making payments with channeld_fakenet.
Note the impedence mismatch between sendpay and getroutes: we have to shift
amounts and delays by 1.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-11-06 21:17:36 +10:30
Rusty Russell
75362d21c5 channeld_fakenet: fake channeld to simulate network given a gossmap_store.
Our gossmap_store uncompresser generates nodeids with well-known
privkeys, so we can decrypt and respond to HTLCs sent to such nodes.
By replacing channeld with a fake, we can connect a node to another
node, but then once the channel is established, allow payments to be
sent into the generated network, and respond appropriately.

This minimal version handles MPP timeouts, but doesn't insert any
delays or runtime capacity for channels.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
Changelog-None: Testing only
2024-11-06 21:17:36 +10:30
Rusty Russell
498111ed8c channeld: routine to feed in a shachain.
This will be used by channeld_fakenet to create replies from the peer.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-11-06 21:17:36 +10:30
Rusty Russell
dca3a8c72c hsmtool: fix NULL secp256k1_ctx when calling dumpcommitments
secp256k1_ctx is used by pubkey_from_node_id.  Don't try to pick and
choose where to initialize secp256k1_ctx, just always do it.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-11-06 21:17:36 +10:30
Rusty Russell
9980931208 doc: don't included stray .md files in index.rst
If you change branches and have a generated .md file, index.rst
will pick it up.  Use the Makefile variable, not the contents of
the filesystem!

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-11-06 21:17:36 +10:30
Lagrang3
ba905f7e20 renepay: add test for description interface
Change-log: renepay: add test for description interface

Signed-off-by: Lagrang3 <lagrang3@protonmail.com>
2024-11-06 09:59:27 +01:00
Lagrang3
2d9277a9a1 renepay: pay BOLT11 invoices with description_hash
This remove an unnecessary check for existing description field if the
description_hash is provided in the invoice. The bolt11_decode function
already checks the description against the hash if both are provided.

Changelog-Fix: renepay: allow to pay BOLT11 invoices with description_hash, the description field is made optional

Signed-off-by: Lagrang3 <lagrang3@protonmail.com>
2024-11-06 09:59:27 +01:00
ShahanaFarooqui
555376e5c7 Remove swagger postman screenshots including .github folder
Fixes: https://github.com/ElementsProject/lightning/issues/7691

Changelog-None.
2024-11-06 14:01:22 +10:30
ShahanaFarooqui
92064706c7 ci: Fixed handling of special characters in PR descriptions while searching for change log none. 2024-11-06 13:48:12 +10:30
ShahanaFarooqui
10898d97e5 script: Giantnode paths fix
Changelog-Fixed: Fixed regtest directory location for giantnode script.
2024-11-06 13:48:12 +10:30
Rusty Russell
b9c718f693 pytest: fix flake in test_sendpay_grouping
Now pay learns, it sometimes learns not to try again:

```
>       assert(len(l1.rpc.listpays()['pays']) == 2)
E       AssertionError: assert 1 == 2
E        +  where 1 = len([{'amount_sent_msat': 0, 'bolt11': 'lnbcrt1pnjj7mysp5tfx8n6nyx7ehszgqn7gqm2r6n079p22u2yddtg797ka3pa9557tspp5f89z6genjqrl3knymvav9ajwcxrm5w7arxux06rrhjux88derjyqdq8v3jhxccxqyjw5qcqp9rzjqgkjyd3q5dv6gllh77kygly9c3kfy0d9xwyjyxsq2nq3c83u5vw4jqqqvuqqqqsqqqqqqqqpqqqqqzsqqc9qxpqysgqcuyr7qlyctf9w96fqg4wetqt7t5v938dagmv0r777n902utjufujzjxl3289r97yngft966zly3ehxfp469dh3lq0hkv6r684snvunqppuyvsl', 'created_at': 1730771812, 'destination': '035d2b1192dfba134e10e540875d366ebc8bc353d5aa766b80c090b39c3a5d885d', ...}])

tests/test_pay.py:5147: AssertionError
```

We fix this by creating a fresh channel, so it will try.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-11-05 17:04:21 +10:30
Rusty Russell
7aef05393c pytest: fix flake in test_onchain_reestablish_reply
We can see peer_in before the state changes:

```
         l3.daemon.wait_for_log("peer_in WIRE_ERROR")
>       assert only_one(l3.rpc.listpeerchannels(l2.info['id'])['channels'])['state'] == 'AWAITING_UNILATERAL'
E       AssertionError: assert 'CHANNELD_NORMAL' == 'AWAITING_UNILATERAL'
E         - AWAITING_UNILATERAL
E         + CHANNELD_NORMAL
```

From the logs, there is 0.2 seconds between them:

```
lightningd-3 2024-11-05T01:58:41.695Z DEBUG   022d223620a359a47ff7f7ac447c85c46c923da53389221a0054c11c1e3ca31d59-channeld-chan#1: peer_in WIRE_ERROR
lightningd-3 2024-11-05T01:58:41.726Z DEBUG   022d223620a359a47ff7f7ac447c85c46c923da53389221a0054c11c1e3ca31d59-channeld-chan#1: billboard perm: Received ERROR channel cecf36a62a09d4f1bdb42aa61d0770964bf3b245b8943a3e5b86dafc572f63d1: Forcibly closed by `close` command timeout
lightningd-3 2024-11-05T01:58:41.745Z UNUSUAL 022d223620a359a47ff7f7ac447c85c46c923da53389221a0054c11c1e3ca31d59-chan#1: Peer permanent failure in CHANNELD_NORMAL: channeld: received ERROR channel cecf36a62a09d4f1bdb42aa61d0770964bf3b245b8943a3e5b86dafc572f63d1: Forcibly closed by `close` command timeout (reason=protocol)
lightningd-3 2024-11-05T01:58:41.890Z DEBUG   022d223620a359a47ff7f7ac447c85c46c923da53389221a0054c11c1e3ca31d59-chan#1: We have 3 anchor points to use
lightningd-3 2024-11-05T01:58:41.897Z DEBUG   lightningd: Broadcasting txid ff2f44b37d96a81fcaa2a4b11746a06be70f3f800fbce941e61a47abb61f70c0
lightningd-3 2024-11-05T01:58:41.901Z DEBUG   lightningd: sendrawtransaction: 02000000000101cecf36a62a09d4f1bdb42aa61d0770964bf3b245b8943a3e5b86dafc572f63d1000000000096b64c80044a01000000000000220020525df7a97bd0506c9ec41ee4e5f095e6e5316db01846a0a687404628017e88494a010000000000002200206db2ec9041ba3ccb6309dcad26015f32637e6869be09d3c3d3a1cb1439296f0b400d030000000000220020c2468acf761754e2533fcb13235326d1f1173b697b132048d6409be7818ed9a96a1f0c0000000000220020b1b561b95c1bccd50fb21bd417a95cabbc3efc351b1353063fe5e9f185d21c8a0400473044022036ab981a2642527c2019a4d15847f6b2fb1d0b92f1a2faff463ab109ed70c4d002205eeb0fcd610a9dba477ee7d66f02d0384080383fbb003d4ee423bdae0970b0430147304402202f7de3481ce00478e539cd9d6bac95ec3c80ec906c46ad2561118dca321b1458022048efd1aa04ff5fafbb99d14f7c9671072b035cbd2c031547793eb0cb6a62302d0147522102d595ae92b3544c3250fb772f214ad8d4c51425033740a5bcc357190add6d7e7a2102d6063d022691b2490ab454dee73a57c6ff5d308352b461ece69f3c284f2c241252ae6e14d920
lightningd-3 2024-11-05T01:58:41.907Z INFO    022d223620a359a47ff7f7ac447c85c46c923da53389221a0054c11c1e3ca31d59-chan#1: State changed from CHANNELD_NORMAL to AWAITING_UNILATERAL
```

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-11-05 17:04:21 +10:30
Vincenzo Palazzo
e1eb5891c4 tests: fix the err msg check
Signed-off-by: Vincenzo Palazzo <vincenzopalazzodev@gmail.com>
2024-11-03 21:38:10 +10:30
Vincenzo Palazzo
6309503692 bolt12: fix typo about parameters name in err str
Changelog-Fixed: bolt12: fix typo about parameters name in err str
Signed-off-by: Vincenzo Palazzo <vincenzopalazzodev@gmail.com>
2024-11-03 21:38:10 +10:30
ShahanaFarooqui
93ba08a537 github: Check if change entry is logged in PR description 2024-11-03 13:15:13 +10:30
Rusty Russell
9b4699077c Github: Belated warning about 24.11 freeze.
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-11-02 13:02:16 +10:30
Rusty Russell
183da392ca connectd: increase queue length to 250,000.
The original complaint which caused my investigation was the 100% CPU
consumption of connectd, which we traced to the queue to gossipd.

However, the issue is not really connectd's overproduction, but
gossipd's underconsumption, probably caused by its own queueing issues
with the trace messages to lightningd, which the prior patch fixed.

Nonetheless, gossipd *can* get busy, and if we were to ask multiple
nodes for full gossip, we could see a few hundred thousand messages
come it at once.  Hence I'm increasing the warning limit to 250,000
messages.

This commit is also where we attach the Changelog message, even
though it's really "common/msg_queue: use membuf for greater efficiency."
and "gossipd: fix excessive msg_queue length from status_trace()" which
solved the problem.

Here's the backtrace from a previous debug patch:

```
lightning_connectd: msg_queue length excessive (version v24.08.1-17-ga780ad4-modded)
0x5580534051f0 send_backtrace
        common/daemon.c:33
0x55805340bd5b do_enqueue
        common/msg_queue.c:66
0x55805340bde5 msg_enqueue
        common/msg_queue.c:82
0x5580534057ce daemon_conn_send
        common/daemon_conn.c:161
0x5580533fe3ff handle_gossip_in
        connectd/multiplex.c:624
0x5580533ff23b handle_message_locally
        connectd/multiplex.c:763
0x5580533ff2d6 read_body_from_peer_done
        connectd/multiplex.c:1112
```

Reported-by: https://github.com/JssDWt
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
Changelog-Fixed: `connectd` and `gossipd` message queues are much more efficient.
2024-11-01 16:54:49 +10:30
Rusty Russell
1efa0653e1 gossipd: fix excessive msg_queue length from status_trace()
When this (very spammy) "handle_recv_gossip" message was changed
from debug to trace, the suppression code wasn't updated: we suppress
overly active debug messages, but not trace messages.

This is the backtrace from an earlier version of the "too large queue"
patch:

```
lightning_gossipd: msg_queue length excessive (version v24.08.1-17-ga780ad4-modded)
0x557e521e833f send_backtrace
        common/daemon.c:33
0x557e521eefb9 do_enqueue
        common/msg_queue.c:66
0x557e521ef043 msg_enqueue
        common/msg_queue.c:82
0x557e521e891d daemon_conn_send
        common/daemon_conn.c:161
0x557e521f14f0 status_send
        common/status.c:90
0x557e521f1804 status_vfmt
        common/status.c:169
0x557e521f1433 status_fmt
        common/status.c:180
0x557e521de7c6 handle_recv_gossip
        gossipd/gossipd.c:206
0x557e521de9f5 connectd_req
        gossipd/gossipd.c:307
0x557e521e862d handle_read
        common/daemon_conn.c:35
```
2024-11-01 16:54:49 +10:30
Rusty Russell
1e4adbff17 common/msg_queue: send backtrace on oversize queues.
Scary looking, but great for debugging!

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-11-01 16:54:49 +10:30
Rusty Russell
1051e97d69 common/msg_queue: use membuf for greater efficiency.
Based on CPU consumption in memmove with the current naive approach.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-11-01 16:54:49 +10:30
ShahanaFarooqui
859f795168 repro: focal modded fix
- Locked grpcio-tools version to fix dirty tree issue. Ref: https://github.com/ElementsProject/lightning/pull/7376#issuecomment-2161102381

- Updated python version to 3.10 for future proofing

- Added manual dispatch for github action
2024-10-31 20:26:30 -07:00
Se7enZ
814c838cae build: Repro build matrix strategy for focal, jammy and noble. ([#7117])
Changelog-None
2024-10-31 20:26:30 -07:00
Se7enZ
f7d3b0bf5a build: Nightly repro build for Ubuntu Noble. 2024-10-31 20:26:30 -07:00
Se7enZ
e004f0075e make: Add a phony version target to output version string. 2024-10-31 20:26:30 -07:00
Alex Myers
80d666b951 gossipd: drive-by correction of new channel announcement evaluation
According to the description, we should be checking the existence of a
channel update on the other side here.

Changelog-None
2024-11-01 13:13:30 +10:30
Rusty Russell
b327bd30c3 doc: fix all JSON schemas to enforce no additional properties.
Without this, we have hardly any enforcement.  This is why the schema
mistake fixed in the previous patches weren't spotted immediately.

The hard work was done by:

```
$ for f in lightning-*.json; do grep -v '^  "additionalProperties": false,' $f | bagto $f; done
$ for f in lightning-*.json; do sed 's/"properties": {/"additionalProperties": false, "properties": {/' $f | bagto $f; done
$ make fmt-schemas
```

Then checking where 'additionalProperties: true' had been turned to
false (we deliberately use it in some places where there are if
statements in the schema, or occasionally where there can be arbitrary
fields).

[Including doc/rpc-schema-draft.json update by Shahana]
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-10-30 15:39:12 +10:30
Rusty Russell
7b2c791dcf doc: fix up missing fields from schemas.
This allows the next patch (which makes the schemas stricter) to not
break our tests.

We add some missing fields (including dev fields, but they're empty and hidden),
and add a few minor clarifications and a spelling fix.  Most of these are new
schemas for this release, so no mention in Changelog.

Here is the difference in the man pages:

    --- doc/lightning-askrene-inform-channel.7.md.old	2024-10-29 17:33:07.714521584 +1030
    +++ doc/lightning-askrene-inform-channel.7.md	2024-10-29 17:42:37.434280109 +1030
    @@ -24,6 +24,8 @@
     - **short\_channel\_id\_dir** (short\_channel\_id\_dir): The short channel id and direction
    +- **layer** (string): The name of the layer to apply this change to.
    +- **timestamp** (u64): The UNIX timestamp when this constraint was created.
     - **maximum\_msat** (msat, optional): The maximum value which this channel could pass.
    --- doc/lightning-askrene-listlayers.7.md.old	2024-10-29 17:33:07.716521571 +1030
    +++ doc/lightning-askrene-listlayers.7.md	2024-10-29 17:42:37.424280316 +1030
    @@ -29,13 +29,16 @@
     - **channel\_updates** (array of objects):
    +  - **short\_channel\_id\_dir** (short\_channel\_id\_dir): The short channel id and direction this update applies to.
    +  - **enabled** (boolean, optional): True if this can be used, false otherwise.
       - **htlc\_minimum\_msat** (msat, optional): The minimum value allowed in this direction.
       - **htlc\_maximum\_msat** (msat, optional): The maximum value allowed in this direction.
       - **fee\_base\_msat** (msat, optional): The base fee to apply to use the channel in this direction.
       - **fee\_proportional\_millionths** (u32, optional): The proportional fee (in parts per million) to apply to use the channel in this direction.
    -  - **delay** (u16, optional): The CLTV delay required for this direction.
    +  - **cltv\_expiry\_delta** (u16, optional): The CLTV delay required for this direction.
     - **constraints** (array of objects):
       - **short\_channel\_id\_dir** (short\_channel\_id\_dir): The short channel id and direction
    +  - **timestamp** (u64, optional): The UNIX timestamp when this constraint was created.
       - **maximum\_msat** (msat, optional): The maximum value which this channel could pass.
    --- doc/lightning-askrene-listreservations.7.md.old	2024-10-29 17:33:07.719521550 +1030
    +++ doc/lightning-askrene-listreservations.7.md	2024-10-29 17:42:37.428280233 +1030
    @@ -16,7 +16,7 @@
    -On success, an object containing **layers** is returned. It is an array of objects, where each object contains:
    +On success, an object containing **reservations** is returned. It is an array of objects, where each object contains:
    --- doc/lightning-autoclean-status.7.md.old	2024-10-29 17:33:07.732521462 +1030
    +++ doc/lightning-autoclean-status.7.md	2024-10-29 17:42:37.441279965 +1030
    @@ -9,7 +9,7 @@
     
    -The **autoclean-status** RPC command tells you about the status of the autclean plugin, optionally for only one subsystem.
    +The **autoclean-status** RPC command tells you about the status of the autoclean plugin, optionally for only one subsystem.
     
    --- doc/lightning-renepay.7.md.old	2024-10-29 17:33:07.927520140 +1030
    +++ doc/lightning-renepay.7.md	2024-10-29 17:42:37.996268504 +1030
    @@ -58,6 +58,9 @@
     - **status** (string) (one of "complete", "pending", "failed"): Status of payment.
    +- **bolt11** (string, optional): The bolt11 invoice paid. *(added v23.08)*
    +- **bolt12** (string, optional): The bolt12 invoice paid. *(added v23.08)*
    +- **groupid** (u64, optional): The groupid used for these payment parts (as can be seen in listsendpays) *(added v23.08)*
     - **destination** (pubkey, optional): The final destination of the payment.
    --- doc/lightning-sendonion.7.md.old	2024-10-29 17:33:07.937520073 +1030
    +++ doc/lightning-sendonion.7.md	2024-10-29 17:42:37.957269309 +1030
    @@ -22,7 +22,7 @@
    -- **first\_hop** (object): Instructs Core Lightning which peer to send the onion to. It is a JSON dictionary that corresponds to the first element of the route array returned by *getroute*.:
    +- **first\_hop** (object): Instructs Core Lightning which peer to send the onion to. It is a JSON dictionary that corresponds to the first element of the route array returned by *getroute* (so fields not mentioned here are ignored).:
    
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
Changelog-EXPERIMENTAL: `renepay` return fields documented in schema (`bolt11`, `bolt12` and `groupid`)
2024-10-30 15:39:12 +10:30
Rusty Russell
fd860f69f8 doc: fix schema for askrene-update-channel.
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-10-30 15:39:12 +10:30
Rusty Russell
916a36a9e4 lightningd: new command injectpaymentonion.
This is like `sendonion` but unwraps the onion as the first hop,
avoiding nasty special cases for blinded paths which start with this
node, and also self-pay.

Tests split into multiple ones after Christian's review.

Changelog-Added: JSON-RPC: `injectpaymentonion` for initiating an HTLC like a peer would do.
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-10-27 13:57:50 +11:00
Rusty Russell
6bfebf4307 lightningd: refactor payment failed.
Don't assume we have an outgoing HTLC at this level.

Note that previously we didn't save the failed onion unless it was
unparsable: we keep that both for space savings and because our
`waitsendpay` logic assumes that when it fetches from the db if
there's a failonion it was unparsable!

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-10-27 13:57:50 +11:00
Rusty Russell
851d8733c6 pytest: generalize serialize_payload_tlv/serialize_payload_final_tlv
Put these in utils and make them a bit more powerful, so we can use
them elsewhere.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-10-27 13:57:50 +11:00
Rusty Russell
6a8e8b2dc9 lightningd: generalize waitsendpay_command so we can use it for injectpaymentonion.
Rather than assuming the callbacks, make them function pointers.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-10-27 13:57:50 +11:00
Rusty Russell
93c1876d1e lightningd: generalize htlc_set.
Make it a set of arbitrary data, so we can use it for local payments,
not just HTLCs.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-10-27 13:57:50 +11:00
Rusty Russell
41610d7bab lightningd: allow htlc_set_fail to take empty msg to send incorrect_or_unknown_payment_details
This message is supposed to include the msat amount received.  But this is
obviously per-HTLC, and we hacked it to use the value for the first one.

And we add logging whenever we fail an HTLC set, since we removed logging
by not calling failmsg_incorrect_or_unknown() (which, now, no longer needs
to log).

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-10-27 13:57:50 +11:00
Rusty Russell
fdb3f5fe1b lightningd: make failmsg_incorrect_or_unknown take amount, not htlc_in.
This makes it slightly more generic.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-10-27 13:57:50 +11:00
Se7enZ
4017844d0c lightningd: listforwards returns 0 for missing received_time. ([#7157])
Removes the `COMPAT_V070` functionality for `listfowards`.

Changelog-Changed: The `listforwards` command will now return a value
of 0 for `received_time` for very old forward attempts.
2024-10-26 09:51:20 +02:00
Se7enZ
3a363df5fb docs: Fix openchannel_abort generated JSON schema.
Changelog-None
2024-10-25 12:13:32 -07:00
Lakshya Singh
9c5e1ca82c docs: openchannel_abort correction
Signed-off-by: Lakshya Singh <lakshay.singh1108@gmail.com>
2024-10-23 22:01:33 +02:00
Se7enZ
4f5ea34461 doc: gRPC SSL custom certificate generation instructions with SANs.
Changelog-Added: Example documentation on generating custom gRPC
certificates with SANs.
2024-10-21 13:58:42 -07:00
Se7enZ
35cda77b3b doc: Fix gRPC custom certificate anchor links. 2024-10-21 13:58:42 -07:00
Joseph Goulden
34187bbf9d doc: Add nix flake documentation to developers guide 2024-10-21 16:56:02 +02:00
Joseph Goulden
d49b5a53fb build: Add cln-postgres package to nix flake 2024-10-21 16:56:02 +02:00
Joseph Goulden
f31a8cf749 build: Update .version as part of the release 2024-10-21 16:56:02 +02:00
Joseph Goulden
fe7168b335 build: Exclude python plugins from flake build 2024-10-21 16:56:02 +02:00
Joseph Goulden
864ece025e build: Add nix derivation for building cargo workspace 2024-10-21 16:56:02 +02:00
Joseph Goulden
2056478e56 build: Add simple flake
Changelog-Added: Nix users can now install CLN from the new flake.
2024-10-21 16:56:02 +02:00
alfredo-toledano
3c3008c5cc doc(README.md): fix typo about supported installation options
Changelog-None
2024-10-21 12:40:28 +02:00
Emmanuel Ferdman
2cb590643f doc: update reference to the generator code
Changelog-None.

Signed-off-by: Emmanuel Ferdman <emmanuelferdman@gmail.com>
2024-10-18 14:01:33 -07:00
ShahanaFarooqui
4f0f84661e release: Update the changelog for point release v24.08.2
Changelog-None.
2024-10-18 09:06:17 -07:00
ShahanaFarooqui
2171583d47 doc: Fix documentation version
Changelog-Fixed: The documentation version was calculated as `pre-v24.08` for point releases like v24.08.1` also because `CLN_NEXT_VERSION` has not been included in the point release branches. Updating the script to build documentation on new tags and change the version to `pre-cln-next-version` for non-tagged commits.
2024-10-17 06:48:08 +10:30
Rusty Russell
fe344ee75b BOLT: update to latest BOLT 3 test vectors.
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-10-16 07:14:32 +10:30
Rusty Russell
905461f7c4 BOLTs: more catchup ("BOLT 4: More clarifying changes.")
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-10-16 07:14:32 +10:30
Rusty Russell
76cfff7533 BOLT update: catch up ("BOLT 4: rename onionmsg_hop to blinded_path_hop")
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-10-16 07:14:32 +10:30
Rusty Russell
f92c9430fd BOLT catchup ("BOLT 4: clarify blinded path requirements.")
This is a significant rework, which lets us clarify a number of our
quotes.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-10-16 07:14:32 +10:30
Rusty Russell
45533584e2 global: rename blinding to path_key everywhere.
Get with the modern nomenclature: the pubkey inside a blinded path is called
the `path_key` now.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-10-16 07:14:32 +10:30
Rusty Russell
9f593a8184 lightningd: update injectonionmessage API to new terminology.
It's not documented, and only used internally, so we don't need a deprecation
cycle.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-10-16 07:14:32 +10:30
Rusty Russell
014459d893 lightningd: update decryptencrypteddata API to new terminology.
It's not documented, and only used internally, so we don't need a deprecation
cycle.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-10-16 07:14:32 +10:30
Rusty Russell
fd717c71af global: deprecate old names in JSON fields, add new ones.
Changelog-Added: JSON-RPC: `decode` now used modern BOLT 4 language for blinded paths, `first_path_key`.
Changelog-Deprecated: JSON-RPC: `decode` `blinding` in blinded path: use `first_path_key`.
Changelog-Added: Plugins: `onion_message_recv` and `onion_message_recv_secret` hooks now used modern BOLT 4 language for blinded paths, `first_path_key`.
Changelog-Deprecated: JSON-RPC: `onion_message_recv` and `onion_message_recv_secret` hooks `blinding` in blinded path: use `first_path_key`.
2024-10-16 07:14:32 +10:30
Rusty Russell
dc18f3cd7b BOLTs: update which renames blinding terminology.
No code changes, just catching up with the BOLT changes which rework our
blinded path terminology (for the better!).

Another patch will sweep the rest of our internal names, this tries only to
make things compile and fix up the BOLT quotes.

1. Inside payload: current_blinding_point -> current_path_key
2. Inside update_add_htlc TLV: blinding_point -> blinded_path
3. Inside blinded_path: blinding -> first_path_key
4. Inside onion_message: blinding -> path_key.
5. Inside encrypted_data_tlv: next_blinding_override -> next_path_key_override

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-10-16 07:14:32 +10:30
Rusty Russell
f944e03fca BOLT update: remove INVALID_REALM error.
This is obsolete (since modern onions) and so removed from spec.
We should not set it, and don't need to handle it specially.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-10-16 07:14:32 +10:30
Rusty Russell
63f971b892 BOLTs: catchup with "Drop the required channel_update in failure onions".
Not much difference for us.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-10-16 07:14:32 +10:30
Rusty Russell
3a9536fd37 BOLT catchup: quiescence is included.
This means we should support it by default.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
Changelog-Added: Protocol: `option_quiesce` enabled by default.
Changelog-Deprecated: Config: --experimental-quiesce: it's now the default.
2024-10-16 07:14:32 +10:30
Rusty Russell
c6be91f8ae wire: add missing patch.
We build with this: it changes the blinded_path field to sciddir_or_pubkey.
But it wasn't committed, so if someone rebuilt the wire files they'd be wrong.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-10-16 07:14:32 +10:30
Rusty Russell
318e49e9c7 askrene: more logging in explain_failure.
Lagrang3 doesn't like the logging in here at all, but he suggested we at
least be consistent!

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-10-15 09:58:04 +10:30
Rusty Russell
95c5fda79f askrene: remove flowset_probability() now refine step calculates it.
Now we've checked it gives the same answers, we can remove a lot of
work in flow.c.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-10-15 09:58:04 +10:30
Rusty Russell
5501e4b13d askrene: use refine step to calculate flowset probability.
Since we know the total reservations on each hop, we can more easily
determine probabilities than using flowset_probability() which has to
replicate this collision detection.

We leave both in place for now, to check.  The results are not
identical, due to slightly different calculation methods.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-10-15 09:58:04 +10:30
Rusty Russell
4b6a38fe0a askrene: fix bug with reservations used during refinement.
We were trying to get the max capacity of a flow to see if we could add some
more sats, and hit an assertion:

tests/test_askrene.py:707: 

```
 DEBUG   plugin-cln-askrene: notify msg info: Flow reduced to deliver 88070161msat not 90008000msat, because 107x1x0/1 has remaining capacity 88071042msat
 DEBUG   plugin-cln-askrene: notify msg info: Flow reduced to deliver 284138158msat not 284787000msat, because 108x1x0/1 has remaining capacity 284141000msat
 **BROKEN** plugin-cln-askrene: Flow delivers 129565000msat but max only 56506138msat
 INFO    plugin-cln-askrene: Killing plugin: exited during normal operation
```

We need to *unreserve* our flow before asking for max capacity.  We were
also missing a few less important cases where we altered flows without altering
the reservation, so fix those too.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-10-15 09:58:04 +10:30
Rusty Russell
bcc8bd59c8 askrene: don't *completely* ignore fees to start.
I noticed that increasing mu a little bit sometimes made a big difference,
because by completely ignoring fees we were choosing the worst of two channels
in some cases.

Start at 1% fees; this saves a lot on initial fees in this test!

Here's the new stats on mu levels:

     96  mu=1
     90  mu=10
     41  mu=20
     30  mu=30
     24  mu=40
     19  mu=50
     22  mu=60
      8  mu=70
     95  mu=80
     19  mu=90

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
Changelog-EXPERIMENTAL: `askrene` is now better at finding low-fee paths.
2024-10-15 09:58:04 +10:30
Rusty Russell
2a0f09fc2d askrene: calculate k value dynamically, using medians.
While the `k=8` value worked for the current main network tests with the
amounts in those tests, it wasn't robust across a wider range of values
(as demonstrated when other test changes broke tests!).

Time to do this properly: calculate the ratio at the time we combine them,
using median values.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-10-15 09:58:04 +10:30
Rusty Russell
32aa79a1e2 askrene: debug and check we actually reduce fees when mu increase.
Even after the previous fix, we still occasionally increase fees when my increases.

This is due to the difference between MCF's linear fees, and actual fees, and
is unavoidable, but add a check if it somehow happens.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-10-15 09:58:04 +10:30
Rusty Russell
08df93cb25 askrene: fix base fee.
I noticed this in the logs:

	plugin-cln-askrene: notify msg unusual: The flows had a fee of 151950msat, greater than max of 53697msat, retrying with mu of 10%...
	plugin-cln-askrene: notify msg unusual: The flows had a fee of 220126msat, greater than max of 53697msat, retrying with mu of 20%...

We would expect increasing mu to *reduce* the fee!

Turns out that our linear fee is a bad terrible approximation, because I
was using base_fee_penalty of 10.0.

 |
 |          /   __ <- real fee, with base: fee = base + propfee * amount.
 |         / __/
 |       _//
 |    __/
 | __/_/
 |/  _/
 | _/ <- linearized fee: fee = linear * amount
 |/
 +-----------------------------------

These cross over where linear = propfee + base / amount.  Assume we split the
payment into 10 parts, this implies that the base_fee_penalty should be 10 / amount
(this gives a slight penalty to the normal case, but that's ok).

This gives better results, too: we get down to 650099 sats in fees, vs 801613
before.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-10-15 09:58:04 +10:30
Rusty Russell
6273adbe47 askrene: calculate prob_cost_factor using ratio of typical mainnet channel.
During "test_real_data", then only successes with reduced fees were 92 on "mu=10", and only
1 on "mu=30": the rest went to mu=100 and failed.

I tried numerous approaches, and in the end, opted for the simplest:

The typical range of probability costs looks likes:
	min = 0, max = 924196240, mean = 10509.4, stddev = 1.9e+06

The typical range of linear fee costs looks like:
	min = 0, max = 101000000, mean = 81894.6, stddev = 2.6e+06

This implies a k factor of 8 makes the two comparable.

This makes the two numbers comparable, and thus makes "mu" much more
effective.  Here are the number of different mu values we succeeded at:

     87  mu=0
     90  mu=10
     42  mu=20
     24  mu=30
     17  mu=40
     19  mu=50
     19  mu=60
     11  mu=70
     95  mu=80
     19  mu=90

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-10-15 09:58:04 +10:30
Rusty Russell
4897286c25 mcf: simplify mu -> cost translation.
The current prob_cost_factor setting does not seem to make mu very
effective, in fact, it gives strange results:

	plugin-cln-askrene: notify msg unusual: The flows had a fee of 151950msat, greater than max of 53697msat, retrying with mu of 10%...
	plugin-cln-askrene: notify msg unusual: The flows had a fee of 220126msat, greater than max of 53697msat, retrying with mu of 20%...

We would expect increasing mu to *reduce* the fee!

As a first step, simplify (it can't be infinite, and the -1 are weird).

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-10-15 09:58:04 +10:30
Rusty Russell
83eee64fda pytest: test askrene with worse maxfee argument.
We ask it again, but reduce fees by 1msat from the previous answer.
This is really nasty, as it frequently exercises the case where we
only go over fee when we do the refinement step.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-10-15 09:58:04 +10:30
Rusty Russell
55fc7fc2e5 pytest: test askrene on real network data.
I checked the failures, they seem real.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-10-15 09:58:04 +10:30
Rusty Russell
f17c5f5a6b askrene: don't use tmpctx in minflow()
I tested with a really large gossmap (hacked to be 4GB), and when we
keep retrying to minimize cost (calling minflow 11 times), and we
don't free tmpctx.

Due to an issue with how gossmap estimates the index sizes, we ended
up running out of memory.  This fixes it.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-10-15 09:58:04 +10:30
Lagrang3
bd8cc1fb1f askrene: detect and cancel flow cycles
Flow cycles can occur if we have arc zero arc costs.
The previous path construction from the flow in the network assumed the
absence of such cycles and would enter an infinite loop if it hit one.

With his patch wee add cycle detection and removal during the path
construction phase.

Reported-by: Rusty Russell <rusty@rustcorp.com.au>
Signed-off-by: Lagrang3 <lagrang3@protonmail.com>
Changelog-EXPERIMENTAL: `askrene` infinite loop fixed
2024-10-15 09:58:04 +10:30
Rusty Russell
d08a3bb9e6 askrene: don't give up if we hit htlc_max and have no other flows.
This happens in the coming "real network" test!

We add fees and hit htlc_max, but don't have another flow to add to.
Rather than MCF again, we split the flow into two.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-10-15 09:58:04 +10:30
Rusty Russell
1b82a3ad5b askrene: constrain to exact htlc_min/htlc_max values.
The fp16_t values are approximations (overestimate for htlc_max,
underestimate for htlc_min), so in the refinement step we should use
the exact values.

This also fixes a logic bug: flow_remaining_capacity returned the
total capacity, not the additional capacity!

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
Changelog-EXPERIMENTAL: `askrene` now honors exact htlc_maximum_msat limits.
2024-10-15 09:58:04 +10:30
Rusty Russell
0baac77a1c gossmap: allow gossmap_chan_get_update_details on locally-modified channels.
In particular, this lets you find the exact htlc_maximum_msat/htlc_minimum_msat
values.

This means we actually create real channel_updates for local mods, which
requires a second "local" scratch region.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-10-15 09:58:04 +10:30
Rusty Russell
4ee9d1d2f2 gossmap: include cltv_expiry_delta in gossmap_chan_get_update_details for completeness.
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-10-15 09:58:04 +10:30
Rusty Russell
22e7a57557 askrene: make auto.sourcefree a real layer, too.
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
Changelog-EXPERIMENTAL: `getroutes` now applies `auto.sourcefree` layer in the order specified, so doesn't alter channels changed in later layers.
2024-10-15 09:58:04 +10:30
Rusty Russell
3321ad5883 askrene: populate auto.localchans layer properly.
Rather than adding to the gossmap modifications directly, populate
the layer and have the normal layer application logic do it.

This is consistent when we query layers in the next patch.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-10-15 09:58:04 +10:30
Rusty Russell
1230f1b832 askrene: give notifications back to caller as we go.
And unify logging for better debugging.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
Changelog-EXPERIMENTAL: `askrene` now has better logging, gives notifications of progress.
2024-10-15 09:58:04 +10:30
Rusty Russell
ca023f2b5e pyln-testing: understand gossip_store_file arg in get_nodes.
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-10-15 09:58:04 +10:30
Rusty Russell
7d02d5749a gossipd: at startup don't send remote channel_update as init update from us.
The "init_cupdate" message is for gossipd to tell lightningd about our *own* latest
channel_update messages, not the remote ones!  The "remote_channel_update" message
is for messages from the peer.

This appeared as an occasional BROKEN message in CI:

```
**BROKEN** 035d2b1192dfba134e10e540875d366ebc8bc353d5aa766b80c090b39c3a5d885d-chan#4: gossipd gave us channel_update for channel in gossip_state CGOSSIP_NEED_PEER_SIGS
```

Where we had sent (and not received) announcement_signatures, and restarted: the peer had meanwhile
sent us their channel_announcement and channel_update.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
Changelog-Fixed: Protocol: we could get confused on restart and not re-transmit our own channel_updates.
2024-10-14 16:58:49 +01:00
Rusty Russell
4e6bac6d36 connectd: fix double-free crash on connection timeout.
tmpctx may not get cleaned immediately, so the timeout (a child of
the struct early_peer at this point) can still outlast the conn.
Do the clearer thing, and explicitly free the timeout.

Changelog-Fixed: connectd: crash on erroneous timeout.
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-10-14 16:36:58 +01:00
Se7enZ
f9e28b9bfa keysend: Add maxfee to keysend for consistency with pay. ([#7227])
Changelog-Added: keysend: Add `maxfee` to keysend for consistency with pay. ([#7227])
2024-10-14 11:58:00 +02:00
Chris Guida
c7189f644a make: Change mv to mv -f when replacing tools/headerversions file
Whenever we build without `make clean` first, this file gets
overwritten. It asks the user for input because it is not run with
`-f`. This causes the build to hang until the user inputs `y`.

Here is an example build:

```
$ make -j7 && sudo make install
CC: cc -DCLN_NEXT_VERSION="v24.08" -DPKGLIBEXECDIR="/usr/local/libexec/c-lightning" -DBINDIR="/usr/local/bin" -DPLUGINDIR="/usr/local/libexec/c-lightning/plugins" -DCCAN_TAL_NEVER_RETURN_NULL=1 -Wall -Wundef -Wmissing-prototypes -Wmissing-declarations -Wstrict-prototypes -Wold-style-definition -Werror -Wno-maybe-uninitialized -Wshadow=local -std=gnu11 -g -fstack-protector-strong -Og -I ccan -I external/libwally-core/include/ -I external/libwally-core/src/secp256k1/include/ -I external/jsmn/ -I external/libbacktrace/ -I external/gheap/ -I external/build-x86_64-linux-gnu/libbacktrace-build -I external/libsodium/src/libsodium/include -I external/libsodium/src/libsodium/include/sodium -I external/build-x86_64-linux-gnu/libsodium-build/src/libsodium/include -I . -I/usr/local/include  -I/usr/include/postgresql    -DSHACHAIN_BITS=48 -DJSMN_PARENT_LINKS  -DCOMPAT_V052=1 -DCOMPAT_V060=1 -DCOMPAT_V061=1 -DCOMPAT_V062=1 -DCOMPAT_V070=1 -DCOMPAT_V072=1 -DCOMPAT_V073=1 -DCOMPAT_V080=1 -DCOMPAT_V081=1 -DCOMPAT_V082=1 -DCOMPAT_V090=1 -DCOMPAT_V0100=1 -DCOMPAT_V0121=1  -c -o
LD: cc   -Og  config.vars  -Lexternal/build-x86_64-linux-gnu -lwallycore -lsecp256k1 -ljsmn -lbacktrace -lsodium -L/usr/local/include -lm -lsqlite3   -L/usr/lib/x86_64-linux-gnu -lpq -o
mv: replace 'tools/headerversions', overriding mode 0755 (rwxr-xr-x)? cc lightningd/test/run-check_node_announcement.c
cc lightningd/test/run-find_my_abspath.c
cc lightningd/test/run-invoice-select-inchan.c
cc lightningd/test/run-jsonrpc.c
cc lightningd/test/run-log_filter.c
cc lightningd/test/run-log-pruning.c
cc lightningd/test/run-shuffle_fds.c
ld lightningd/test/run-find_my_abspath
ld lightningd/test/run-log-pruning
ld lightningd/test/run-check_node_announcement
ld lightningd/test/run-log_filter
ld lightningd/test/run-jsonrpc
ld lightningd/test/run-shuffle_fds
ld lightningd/test/run-invoice-select-inchan
^Cmake: *** [tools/Makefile:16: tools/headerversions] Interrupt
```

One workaround is to just know that you need to enter `y` here.
But the best solution is probably to update the Makefile like so.

Changelog-None
2024-10-14 15:00:36 +10:30
Jesse de Wit
8330e3a0df pay-plugin: set gossmods directly
Multiple places in the pay lifecycle depend on mods to be set. By
setting the mods directly after the first listpeerchannels call,
subsequent calls to listpeerchannels are avoided.

Changelog-Fixed: pay-plugin: only call listpeerchannels once during a
payment lifecycle.
2024-10-08 19:26:14 +02:00
Jesse de Wit
281c639b57 pay-plugin: direct_pay only destination channels
The direct_pay payment modifier would query all peer channels, while
only the channels of the given peer suffices.

Changelog-None
2024-10-08 19:26:14 +02:00
Tommy Volk
6bd5933a50 chore: bump rust bitcoin to 0.31 2024-10-08 18:56:05 +02:00
ShahanaFarooqui
910c014183 ci: Prebuild action fails if Changelog is missing from all commits of a PR
Changelog-None.
2024-10-08 18:31:40 +02:00
Rusty Russell
d067066b17 common/gossmap: use u64 for all offsets.
Since we don't compact the gossmap on the fly (FIXME!) we can
easily surpass 4GB in the gossmap, and 32 bit offsets are not
sufficient.

I'm a bit surprised we don't crash immediately, but we've definitely
seen issues.

Changelog-Fixed: gossipd: crash errors with large gossip_store (>4MB) growth on longer-running nodes.
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-10-08 09:50:17 +02:00
Rusty Russell
ebf784ef9c gossipd: use u64 for the one offset we don't.
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-10-08 09:50:17 +02:00
Jesse de Wit
cc1362ead3 libplugin-pay: use map for channel hints
For nodes with many channels this is a tremendous improvement in pay
performance. PR #7611 improves payment performance from 15 seconds to
13.5 seconds on one of our nodes. This commit improves payment
performance from 13.5 seconds to 5.7 seconds.

Changelog-Fixed: Improved pathfinding speed for large nodes.
2024-10-07 15:16:46 +02:00
Christian Decker
a6a7dd8f71 pay: Switch to msat for total_capacity
This minimizes the need to convert back and forth from and to sat
values, and it also removes a new instance of sats in the public
interface (`channel_hints`).

Suggested-By: Rusty Russell <@rustyrussell>
2024-10-07 14:05:47 +02:00
Christian Decker
ddc199ff41 route: Re-add the assertion that we're one side of a channel 2024-10-07 14:05:47 +02:00
Christian Decker
3845b84dbc pay: Simplify the channel_hint update logic
We were ignoring more reliable information because of the
stricter-is-better logic. This meant that we were also ignoring local
channel information, despite knowing better.

By simplifying the logic to pick the one with the newer timestamp we
ensure that later observations always trump earlier ones. There is a
bit of interplay between the relaxation of the constraints updating
the timestamp, and comparing to real observation timestamps, but that
should not impact us for local channels.
2024-10-07 14:05:47 +02:00
Christian Decker
db36449408 pytest: Fix up the test_sendpay_grouping test
It was failing because the channel_hint from one attempt would prevent
us from retrying. By changing the amounts so that the channel_hints do
not concern them (value smaller than estimate) we can make things work
as before again.
2024-10-07 14:05:47 +02:00
Christian Decker
e839c0ebcc test: Fix up the test_pay_routeboost test 2024-10-07 14:05:47 +02:00
Christian Decker
63e663ec9c pytest: Fix up the test_mutual_connect_race
A failing payment would doom all subsequent ones. Now we step down the
amount a single satoshi so any prior channel_hints do not doom the
payment outright.

Changelog-None
2024-10-07 14:05:47 +02:00
Christian Decker
f6d410d924 pay: Remove use of temporary local channel_hint
We were using `channel_hint` to temporarily tweak the graph inside of
a payment. However, these ad-hoc `channel_hints` are stickier than
their predecessors, in that they outlive the payment attempt itself,
and interfere with later ones.

Changelog-Changed: pay: Discarding an overly long or expensive route does not blocklist channels anymore.
2024-10-07 14:05:47 +02:00
Christian Decker
0a62416c4b pay: Inject channel_hints we receive via plugin notifications
Making sure that we don't accidentally create an endless loop.
2024-10-07 14:05:47 +02:00
Christian Decker
30d2a57f50 pay: Log when and why we exclude a channel from the route 2024-10-07 14:05:47 +02:00
Christian Decker
91ffa8e424 pay: Add channel_hint_set_count primitive 2024-10-07 14:05:47 +02:00
Christian Decker
30a2933a94 pay: Add a hysteresis for channel_hint relaxation
If we have a large channel, fail to send through a small amount, and
then add a `channel_hint`, then it can happen that the call to
`channel_hint_set_update` is already late enough that it refills the
1msat we removed from the attempted amount, thus making the edge we
just excluded eligible again, which can lead into an infinite loop.

We slow down the updating of the channel_hints to once every
hysteresis timeout. This allows us to set tight constraints, while not
incurring in the accidental relaxation issue.
2024-10-07 14:05:47 +02:00
Christian Decker
50a0321759 pay: Use the global channel_hint_set and remember across payments 2024-10-07 14:05:47 +02:00
Christian Decker
603a70e7e2 pytest: Test that we remember learnt channel hints across payments 2024-10-07 14:05:47 +02:00
Christian Decker
3ad0085478 route: Change the type of the funding capacity to amount_sat
Keeping it in `amount_msat` made the comparisons easier, but it was
the wrong type for this.
2024-10-07 14:05:47 +02:00
Christian Decker
f803af782a route: Use safe amount_sat_to_msat conversion
Suggested-by: Rusty Russell <@rustyrussell>
2024-10-07 14:05:47 +02:00
Christian Decker
904eb3795c pay: Subscribe to the channel_hint_update notifications 2024-10-07 14:05:47 +02:00
Christian Decker
29df2c9f40 route: Simplify direction 2024-10-07 14:05:47 +02:00
Christian Decker
cf09314b3b pay: Rename overall_capacity to just capacity
Suggested-by: Rusty Russell <@rustyrussell>
2024-10-07 14:05:47 +02:00
Christian Decker
37a204df41 plugin: Split out the struct channel_hint handling
We're getting serious about how we manage the channel_hints, so let's
give them a proper home.
2024-10-07 14:05:47 +02:00
Christian Decker
1144088e14 make: Weaken over aggressive check-amount-access test
Changelog-None
2024-10-07 14:05:47 +02:00
Christian Decker
b897b4365d pay: Make the channel_hints global
We attach the hints to the plugin, so they get shared across multiple
payments.
2024-10-07 14:05:47 +02:00
Christian Decker
5225218094 pay: Use the total_mast amount as the upper limit for channel_hints 2024-10-07 14:05:47 +02:00
Christian Decker
1eb878be82 route: Add the total capacity to route_hops
We need to know the overall channel capacity, i.e., the amount_msat
that the channel was funded with, in order to relax the channel_hint
to refill over time.
2024-10-07 14:05:47 +02:00
Christian Decker
d60db28c41 pay: Add a function to update channel_hints based on their age
We relax constraints from the `channel_hint` through a linear refill.
2024-10-07 14:05:47 +02:00
Jesse de Wit
538a0076ca topology: call listpeerchannels_done directly
When cln is run without deprecated apis, the `listchannels` call would
still query `listpeerchannels`, even though it wouldn't use the result.
This adds unnecessary time to the call. Especially in case the node has
many channels. This commit skips the listpeerchannels call in case the
outcome won't be used.

Changelog-Fixed: Improve listchannels performance
2024-10-04 17:51:55 +02:00
ShahanaFarooqui
81e30eab52 docs: Updating release checklist with Hotfix release instructions
Changelog-None.
2024-10-03 22:24:56 -07:00
Se7enZ
fea30491c3 doc: Include documentation for test targeting via PYTEST_TESTS.
Also update the table of optional environment variables to set when
running the integration tests.
2024-10-03 21:51:26 -07:00
Se7enZ
537d613035 pytest: Support targeting specific tests using make pytest.
Select tests by setting the `PYTEST_TESTS` environment variable.

Changelog-None
2024-10-03 21:51:26 -07:00
Se7enZ
cbe94bcb42 pyln-testing: Fix file descriptor leak in bitcoind fixture. ([#7130])
Changelog-Fixed: pyln-testing: Fix file descriptor leak in bitcoind fixture. ([#7130])
2024-10-03 19:04:35 -07:00
Aditya Sharma
27b4a03419 tests: Add test_getemergencyrecoverdata to test the RPC getemergencyrecoverdata. 2024-10-03 18:59:10 -07:00
Aditya Sharma
2be7433ae6 doc: Add documentation for the RPC getemergencyrecoverdata. 2024-10-03 18:59:10 -07:00
Aditya Sharma
4c775f16aa plugins/chanbackup: Add RPC to fetch data from emergency.recover file. 2024-10-03 18:59:10 -07:00
Rusty Russell
b8acd3b37c askrene: more code tweaks on feedback from Lagrang3.
1. describe_disabled should point out if node itself is disabled.
2. Hoist constraint check for neater if branching.
3. Use amount_msat_max/min for greater clarity.
4. Simply disable channels, don't zero htlc_min/max when node disabled.

I also fixed the diagnostic of htlc_max correctly, which removes a FIXME.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-10-04 11:27:53 +09:30
Rusty Russell
e3c9bc6d3a askrene: trivial changes to avoid -O3 compiler warnings.
The code is a bit too complex for gcc to track it:

```
In file included from ccan/ccan/tal/str/str.h:7,
                 from plugins/askrene/askrene.c:11:
plugins/askrene/askrene.c: In function ‘do_getroutes’:
ccan/ccan/tal/tal.h:324:23: error: ‘routes’ may be used uninitialized in this function [-Werror=maybe-uninitialized]
  324 | #define tal_count(p) (tal_bytelen(p) / sizeof(*p))
      |                       ^~~~~~~~~~~
plugins/askrene/askrene.c:476:24: note: ‘routes’ was declared here
  476 |         struct route **routes;
      |                        ^~~~~~
plugins/askrene/askrene.c:475:29: error: ‘amounts’ may be used uninitialized in this function [-Werror=maybe-uninitialized]
  475 |         struct amount_msat *amounts;
      |                             ^~~~~~~
plugins/askrene/askrene.c:488:69: error: ‘probability’ may be used uninitialized in this function [-Werror=maybe-uninitialized]
  488 |         json_add_u64(response, "probability_ppm", (u64)(probability * 1000000));
      |                                                        ~~~~~~~~~~~~~^~~~~~~~~~
cc plugins/askrene/dijkstra.c
cc1: all warnings being treated as errors
```

On my local machine, it also warns in param_dev_channel, so I fixed that too.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-10-04 11:27:53 +09:30
Rusty Russell
630ec6a566 askrene: give better feedback when we can't find a suitable route.
This turns out to be critical for users: also stops them from
bothering us when their node is offline or has insufficient capacity!

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-10-04 11:27:53 +09:30
Rusty Russell
e54c0f8ded askrene: don't replace constraints, simply accumulate.
Lagrang3 points out it's less useful (when we time them out), and probably
a premature optimization anyway.

Suggested-by: Lagrang3 <lagrang3@protonmail.com>
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-10-04 11:27:53 +09:30
Rusty Russell
c307b77d2f askrene: split askrene-create-channel into create-channel and update-channel.
This allows for explicit partial updates to channels (e.g. just change
fees, or just disable) without haveing to set the other fields.

This generalizes askrene-disable-channel, which is removed.

We also take the chance to use the proper BOLT 7 terms in the API:

- htlc_minimum_msat
- htlc_maximum_msat
- cltv_expiry_delta
- fee_base_msat
- fee_proportional_millionths

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-10-04 11:27:53 +09:30
Rusty Russell
5052f0763f gossmap: keep capacity for locally-generated channels as well.
It was weird not to have a capacity associated with localmods channels, and
fixing it has some very nice side effects.

Now the gossmap_chan_get_capacity() call never fails (we prevented reading
of channels from gossmap in the partially-written case already), so we
make it return the capacity.  We do this in msat, because that's what
all the callers want.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-10-04 11:27:53 +09:30
Rusty Russell
a60063e763 common/gossmods_listpeerchannels: include channel capacity in callback.
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-10-04 11:27:53 +09:30
Rusty Russell
a65e325b13 gossmap: implement partial updates.
This is actually what we want in several places: to only override one or
two fields in a channel_update.

We add a gossmap_local_setchan() with a similar API to the old
gossmap_local_updatechan(), for the case where we want to set every
field.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-10-04 11:27:53 +09:30
Rusty Russell
bb3663c4a0 askrene: ignore disabled channels for min-cost-flow.
We also set htlc_max to 0 when disabling, so the tests worked, but
this is correct.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-10-04 11:27:53 +09:30
Rusty Russell
154ad585ec pytest: enhance test_getroutes_auto_sourcefree with same case *without* auto.sourcefree.
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-10-04 11:27:53 +09:30
Rusty Russell
3253623785 gossmods_from_listpeerchannels: use correct type for cltv_delta.
Doesn't matter now, but will with the next change where we want to
pass a pointer.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-10-04 11:27:53 +09:30
Rusty Russell
fcc0d2bad8 askrene: remove unused parameter in layer_add_localmods.
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-10-04 11:27:53 +09:30
Rusty Russell
321ec0875f askrene: rework constraints to exist in pairs.
This is a bit more efficient, but moreover the JSONRPC API is more
logical this way.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-10-04 11:27:53 +09:30
Rusty Russell
3c5c22b17a askrene: change inform interface, take into account reserve.
Lagrang3 points out that if we hit a maximum, we should take into account
the reserve.  This is true, but it's hard for the caller to do, so change
the API to be slightly higher level.

Tell "inform" what happened, and it adjust the constraints appropriately.
This makes the least assumptions possible (a reserve does *not* mean that
the capacity was actually used at that time).

We also add a mode to say "this succeeded": for now this does nothing,
but it could reduce both min/max capacities, and add capacity in the
other direction.  This is useful for future payments, but not as useful
for the current one.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-10-04 11:27:53 +09:30
Rusty Russell
d50838b60f askrene: implement listreservations
And actually write tests!

Suggested-by: Lagrang3 <lagrang3@protonmail.com>
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-10-04 11:27:53 +09:30
Rusty Russell
0398d2ff73 askrene: remember individual reservations, for better debugging.
Suggested-by: Lagrang3 <lagrang3@protonmail.com>
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-10-04 11:27:53 +09:30
Rusty Russell
10dc40a895 askrene: clean up reserve array handling.
I got confused, as we had a struct containing two arrays.  Simply expose the
reserve_hop struct and use arrays directly.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-10-04 11:27:53 +09:30
Rusty Russell
2df53c32c2 askrene: make route_query contain pointer to the command.
This is important for errors and feedback.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-10-04 11:27:53 +09:30
Rusty Russell
b88f4cb854 askrene: askrene-create-layer and askrene-remove-layer.
It's generally better to be explicit with these things: currently typos
would be ignored.  But it's also much easier to clean up entire layers
as we use them for temporary (per-payment) effects.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-10-04 11:27:53 +09:30
Rusty Russell
29cc227a53 askrene: use short_channel_id_dir in API.
It's generally much more convenient, and it's already present in
other APIs.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-10-04 11:27:53 +09:30
Lagrang3
33404b03a0 add askrene-disable-channel
Changelog-EXPERIMENTAL: askrene: add askrene-disable-channel RPC
Signed-off-by: Lagrang3 <lagrang3@protonmail.com>
2024-10-04 11:27:53 +09:30
Rusty Russell
f46219b505 common: round out the short_channel_id_dir JSON routines.
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-10-04 11:27:53 +09:30
Rusty Russell
d8ca9baa3b askrene: add support for disabled channels in layers.
Based-on-the-patch-by: Lagrang3 <lagrang3@protonmail.com>
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-10-04 11:27:53 +09:30
Rusty Russell
bc1aabb014 gossmap: don't crash on localmods on non-existant channels.
We allow adding them, but crash when we remove the localmods.  Yet
this could theoretically happen if a channel we modified was removed
from the gossmap, anyway.

Reported-by: Lagrang3 <lagrang3@protonmail.com>
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-10-04 11:27:53 +09:30
Rusty Russell
0a23c63d37 askrene: optimize, by calling tal_count less.
I like the clarity, but this is a hot path.  Fortunately these arrays
have very well defined lengths.

Before: 5.81 seconds
After: 1.06 seconds

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-10-04 08:47:53 +09:30
Rusty Russell
9f0c0e1cca askrene: use a simple array as our queue.
We only ever visit each node once, so we can just use an array.  This
avoids calling tal() all the time, which is *especially* slow when we're
memory tracking.

I had an old canned gossmap which I benchmarked for these (and in
particular one node was unreachable, and that was slow):

Before: 17.27 seconds
After: 5.80 seconds

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-10-04 08:47:53 +09:30
Rusty Russell
79fa3d3d7a tests/data: add compressd canned gossip from mainnet.
We can run a lot of tests on this.

Look at me, I'm number 3301!

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-10-04 08:47:53 +09:30
Rusty Russell
d1a6649c73 gossmap-compress: warn about updates which we don't include in map.
There are some, they're unusable high-fee.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-10-04 08:47:53 +09:30
Rusty Russell
01b65d1a15 gossmap: print out nodeids and aliases, so you can map them back after compression.
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-10-04 08:47:53 +09:30
Rusty Russell
e55a4850cc devtools/gossmap-compress: fix channels.
We can only use the loop to iterate once.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-10-04 08:47:53 +09:30
Rusty Russell
d143c22976 gossmap-compress: sort nodes into most to least as intended.
Interestingly, compressed sizes don't change, but uncompressed does:

```
$ file /tmp/gs.out-wrongorder
/tmp/gs.out-wrongorder: gzip compressed data, max compression, from Unix, original size modulo 2^32 1594822
$ ls -l /tmp/gs.out-wrongorder 
-rw-rw-r-- 1 rusty rusty 494337 Sep 20 13:34 /tmp/gs.out-wrongorder
$ file /tmp/gs.out
/tmp/gs.out: gzip compressed data, max compression, from Unix, original size modulo 2^32 1498634
$ ls -l /tmp/gs.out
-rw-rw-r-- 1 rusty rusty 494353 Sep 20 13:33 /tmp/gs.out
```

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-10-04 08:47:53 +09:30
ShahanaFarooqui
7ac32ebbf8 Update pyln-client for clnrest 2024-10-03 11:20:52 -07:00
Rusty Russell
00e0b99d3a hsmtool: provide nodeid from hsm secret.
This allows tools to validate that it is accessing the correct hsm_secret for this node!

This is extremely important for backups: if they are using VLS, they need to back *that*
up instead, for example.

Changelog-Added: `hsmtool`: `getnodeid` command derives the node id from the hsm_secret, to verify it's the correct secret.
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-09-25 12:07:40 -07:00
ShahanaFarooqui
e36b68ab48 gpg: New public key
Changelog-None.
2024-09-24 21:00:25 -07:00
Rusty Russell
21fcd4594b cln-rpc/src/model.rs: fix difference between master and my machine.
Not sure why this differs from master, so trying pushing my version
to master?

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-09-24 10:24:51 +09:00
niftynei
5ae7212e37 anchors: dont include utxos which are csv locked
When building a tx to spend *now* we shouldn't include CSV locked utxos
as we want them to be immediately spendable.
2024-09-23 11:39:33 -07:00
Peter Neuroth
0a6870f13d rust-libs: Bump versions
We bump the version to minor version 0.2 to allow ourselves to bump on
patch level when we need to fix a bug or update a dependency.

Changelog-Changed: Plugins: `cln-grpc` Upgrade tonic version and
introduce new versioning scheme.

Signed-off-by: Peter Neuroth <pet.v.ne@gmail.com>
2024-09-22 00:12:39 -07:00
Peter Neuroth
a6366c2814 rust-libs: Upgrade tonic to v0.12
Tonic had some breaking changes since 0.8. We want to be closer to newer
versions for downstream consumers to be able to benefit from changes in tonic.

Signed-off-by: Peter Neuroth <pet.v.ne@gmail.com>
2024-09-22 00:12:39 -07:00
Jesse de Wit
2798b4b7be cln-grpc: add anchors/even to primitives
The `anchors/even` channel type was missing from the grpc bindings.
It is now the default channel type, so `fundchannel` over grpc fails
with:

```
Failed to deserialize response : unknown variant `anchors/even`,
expected one of `static_remotekey/even`, `anchor_outputs/even`,
`anchors_zero_fee_htlc_tx/even`, `scid_alias/even`, `zeroconf/even`
```

Changelog-Changed: Channel type `anchors/even` was added
to the grpc bindings.
2024-09-20 17:01:04 -07:00
Rusty Russell
aba67a757c lightningd: rename state_change_entry to channel_state_change, and use pointers.
This name is clearer than the old one.

And since the struct contains a string, it's more natural for the
struct to be the tal parent of the string so it's a real object.  This means
we need an array of pointers, so each struct can be its own tal object.

wallet_state_change_get is hoisted higher in the code and made static.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-09-21 06:20:18 +09:30
Rusty Russell
0440700132 lightningd: move the state changes into struct channel.
And instead of loading them in listpeerchannels, use them.  This means
listpeerchannels no longer touches the db.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
Changelog-Fixed: JSONRPC: `listpeerchannels` (and thus, pay) sped up on very large nodes.
2024-09-21 06:20:18 +09:30
Rusty Russell
eb979980a9 db: clean up channel_stats handling.
Indirection via a string and an enum is just adding confusion here.

And move the `struct channel_stats` into channel.h.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-09-21 06:20:18 +09:30
Rusty Russell
3aace10828 listpeerchannels: use struct channel stats, don't fetch from db.
This avoids a db lookup on every iteration of listpeerchannels, which
can be slow on large nodes (Postgres, I assume).

We can now simply add the fields we want to channel load, and remove
wallet_channel_stats_load entirely.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-09-21 06:20:18 +09:30
Rusty Russell
762d624810 lightningd: move stats into struct channel.
Like other fields, mirror them into the db.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-09-21 06:20:18 +09:30
Lagrang3
0aa52b7fdd askrene: remove unused function
Signed-off-by: Lagrang3 <lagrang3@protonmail.com>
2024-09-19 12:16:53 +09:30
Rusty Russell
9b60f6cc6d askrene: re-check min_htlc violations after correcting for MCF rounding.
Thanks to @Lagrang3 for spotting this!

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-09-19 12:16:53 +09:30
Rusty Russell
8c551ae48a askrene: move flow refining code to its own file.
askrene.c was getting quite long, and this is self-contained.

The only code change is a convenience accessor for the per-htlc-cost
hash table.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-09-19 12:16:53 +09:30
Rusty Russell
9d966b46a7 askrene: take into account the reduction in "spendable" with additional HTLCs.
"spendable" is for a single HTLC: if we own the channel, this amount
decreases with every HTLC, as we have to pay fees.  We have access to this since
we call listpeerchannels anyway, so we can calculate the additional costs and
use it in the refining phase.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-09-19 12:16:53 +09:30
Rusty Russell
3e96955c72 pytest: test askrene treats htlc_maximum_msat and htlc_minimum_msat restrictions properly.
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-09-19 12:16:53 +09:30
Rusty Russell
db29a2d6b5 askrene: don't have get_flow_paths() handle htlc_max, htlc_min and extra millisats.
We don't actually hit the htlc_max cases, since the flow code already
constrains us to that.

And handling htlc_min is better done in the caller, where diagnostics
are better (basically, we should eliminate them, and if that means no
route, give a clear error message).

And the refinement step can handle any extra millisats from rounding.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-09-19 12:16:53 +09:30
Rusty Russell
f0331cd82e askrene: add a "refining" step to add fees and handle corner cases.
This is the root cause of the problem worked around in 50949b7b9c
"askrene: hack in some padding so we don't overflow capacities."

When adding fees to flows, we didn't recheck the boundary conditions: in
renepay this is done by routebuilder.

Fortunately, we can use our "reservations" infrastructure to temporarily
use capacity as we process flows, so we handle the cases where they are
not independent correclty.

My assumption is that the resulting errors are small, so we divide
them between the remaining flows based on highest-to-least
probability.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-09-19 12:16:53 +09:30
Rusty Russell
5883aa85ca askrene: rename struct flow amount to delivers.
This is clearer: it's the final amount, not the amount we send!

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-09-19 12:16:53 +09:30
Rusty Russell
829954ac71 askrene: remove struct flow probability member.
Simply calculate it when we need it, which means we don't have to keep it
up-to-date as we tweak the flow.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-09-19 12:16:53 +09:30
Rusty Russell
923e37a545 askrene: remove unused flow routines.
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-09-19 12:16:53 +09:30
Rusty Russell
17191259ea patch libplugin-batch.patch 2024-09-19 12:16:53 +09:30
Rusty Russell
1362448352 common/bolt12: do more required checks in invoice_decode.
Rather than making the callers do this, make the invoice decoder perform
the various sanity checks.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-09-19 12:16:53 +09:30
Rusty Russell
1b8a64f5e6 askrene: apply "auto.sourcefree" to channels created in layers, too.
We had a workaround for channels added by "auto.local", but instead we
should make it work properly.

I didn't do this before because we can't manipulate the localmods while
they're applied, but it's simple to do it in two stages.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-09-19 12:16:53 +09:30
Rusty Russell
06957dc832 pytest: separate out routine which checks only some fields of getroutes.
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-09-19 12:16:53 +09:30
Rusty Russell
e90be8d957 pyln-testing: add gossip_store_file arg to get_node()
This makes it much easier to use generated gossip_store files.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-09-19 12:16:53 +09:30
Rusty Russell
5ea049ea12 pytest: duplicate test_live_spendable as a canned gossmap test.
Not quite the same, as it doesn't have the "auto.local" layer, but it exhibits
the same problem if we revert the fix for test_live_spendable.

And it's much faster!

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-09-19 12:16:53 +09:30
Rusty Russell
b11642538e pytest: ensure there are no duplicate paths in test_live_spendable, and check total.
There aren't, but make sure.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-09-19 12:16:53 +09:30
Rusty Russell
679f46f733 common/amount: rename amount_sat_zero/amount_msat_zerp -> amount_sat_is_zero/amount_msat_is_zero.
I used `amount_msat_eq(x, AMOUNT_MSAT(0))` because I forgot this
function existed.  I probably missed it because the name is surprising,
so add "is" in there to make it clear it's a boolean function.

You'll note almost all the places which did use it are Eduardo's and
Lisa's code, so maybe it's just me.

Fix up a few places which I could use it, too.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-09-19 12:16:53 +09:30
Rusty Russell
f05f871c92 common/amount: add amount_msat_accumulate()
Saves some typing, and is clearer than checking if both args really
are the same!

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-09-19 12:16:53 +09:30
Rusty Russell
6150d1b3fa patch general-node-id-assign.patch 2024-09-19 12:16:53 +09:30
Rusty Russell
379a4ee16a common/amount: add routine to calculate fees backwards.
If I put in X, how much can I get out after fees are subtracted?

This was inspired by Eduardo's channel_maximum_forward in renepay, which
is basically the same thing.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-09-19 12:16:53 +09:30
Rusty Russell
db74ca7cbe lightningd: remove incorrect old-payment-htlc-delete logic.
This was incorrect once we stopped removing old payments on failure,
which was the reason we had to remove the HTLCs.

It also removed by partid, which is wrong since it should have done
old_payment->partid and old_payment->groupid!

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-09-19 12:16:53 +09:30
ShahanaFarooqui
75c616c7b3 Makefile: Next version updated to 24.11
Changelog-None.
2024-09-18 16:59:27 +09:30
ShahanaFarooqui
5ba1824fd5 doc: Release checklist update 2024-09-18 16:59:27 +09:30
ShahanaFarooqui
8558993f77 doc: Pull request template update 2024-09-18 16:59:27 +09:30
ShahanaFarooqui
3d3e86e22c test: CI error fixes
- Removes CI value error for Broken logs
- Fixes CI errors due to deprecated listconfigs 'important-plugins'
- Removed listchannels deprecated local test

Changelog-None.
2024-09-18 16:59:27 +09:30
Michael Schmoock
02176f7004 pytests: extend the offline mode testcase 2024-09-17 19:53:25 +02:00
ShahanaFarooqui
7725ca1dbc meta: Add changelog for hotfix release v24.08.1
Changelog-None.
2024-09-17 10:24:24 -07:00
Rusty Russell
f0cf088489 lightningd: don't crash if plugin dies during initial plugins_init.
Thanks to Michael Schmook for the excellent bug report.

Fixes: https://github.com/ElementsProject/lightning/issues/7671
Changelog-Fixed: lightningd: no longer crash if a plugin dies during lightningd startup.
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-09-17 10:24:01 -07:00
Rusty Russell
f4f6279b17 pytest: thoroughly test plugin death during startup.
We modify broken.py to be able to fail at different points,
and test that during startup.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-09-17 10:24:01 -07:00
Rusty Russell
4578748aca plugins/Makefile: fail if jq command fails.
Nested within the loop, jq would fail silently.

This can happen if jq is too old.

Fixes: https://github.com/ElementsProject/lightning/issues/7657
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-09-17 17:02:22 +02:00
Rusty Russell
5c870c90a6 configure: ensure that we have jq.
Otherwise we can get other crashes it seems?

Fixes: https://github.com/ElementsProject/lightning/issues/7657
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-09-17 17:02:22 +02:00
laanwj
9e8dd15a99 cln-plugin: Change default log level filter back to INFO
In commit 60e1532dd8 (released in crate 0.1.8), which switched the
logging framework to tracing-subscriber, the default log level filter
was (accidentally) set to ERROR and above, instead of INFO and above.

Change this back to INFO as it was before. It can still be overridden
with CLN_PLUGIN_LOG.

Follows the example in https://docs.rs/tracing-subscriber/latest/tracing_subscriber/filter/struct.EnvFilter.html#method.from_env

Closes #7658.

Changelog-Fixed: cln-plugin: Change default log level filter back to INFO
2024-09-17 12:00:27 +09:30
Rusty Russell
bfe0557f0b topology: fix overzealous deprecation check in listpeerchannels.
It's an output field (which we don't complain about), not an input field!

Fixes: https://github.com/ElementsProject/lightning/issues/7652
Changelog-Fixed: Logging: removed bogus "**BROKEN** plugin-topology: DEPRECATED API USED: listchannels.include_private" message.
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-09-16 16:03:48 +09:30
Rusty Russell
7e2ea3ed04 pytest: add test for bogus deprecation BROKEN log.
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-09-16 16:03:48 +09:30
laanwj
c8660c85ba schemas: "description" field in "wait(any)invoice" is optional since BOLT12
For BOLT12 invoices, the "description" is field missing in the invoice
responses. Update the schemas accordingly:

- `doc/schemas/lightning-waitanyinvoice.json`
- `doc/schemas/lightning-waitinvoice.json`

Also commit the generated msggen, cln-grpc, cln-rpc and pyln-grpc-proto files.

Changelog-Fixed: schemas: Make description in `Wait(any)invoiceResponse` optional to handle BOLT12
2024-09-16 16:03:07 +09:30
Rusty Russell
5bd3d51131 subds: fix case where we keep retrying on EOF.
Our low-level ccan/io IO routines return three values:
-1: error.
0: call me again, I'm not finished.
1: I'm done, go onto the next thing.

In the last release, we tweaked the sematics of "-1": we now opportunistically
call a routine which returns 0 once more, in case there's more data.  We use errno to
distinguish between "EAGAIN" which means there wasn't any data, and real errors.

However, if the underlying read() returns 0 (which it does when the peer has closed
the other end) the value of errno is UNDEFINED.  If it happens to be EAGAIN, we will
call it again, rather than closing.  This causes us to spin: in particular people reported
hsmd consuming 100% of CPU.

The ccan/io read code handled this by setting errno to 0 in this case, but our own
wire low-level routines *did not*.

Fixes: https://github.com/ElementsProject/lightning/issues/7655
Changelog-Fixed: Fixed intermittant bug where hsmd (particularly, but also lightningd) could use 100% CPU.
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-09-13 11:13:53 -07:00
Rusty Russell
c5fc1b55d8 lightningd: make sure channels always have a local alias.
If we pull and old channel from the database, it might not.

Fixes: https://github.com/ElementsProject/lightning/issues/7645
Changelog-Fixes: lightningd: crash when starting channeld for older channel with no local alias.
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-09-13 14:09:58 +09:30
Lagrang3
2bd9c2285a lightningd: log if builtin plugin fails to start
Lightningd should log if a builtin plugin fails to start instead of
silently skip over it.

Changelog-Add: log message if builtin plugin fails to start.

Signed-off-by: Lagrang3 <lagrang3@protonmail.com>
2024-09-10 08:34:49 -07:00
Rusty Russell
78b9ccf432 channeld: fix crash with pre-TLV peers.
send_tlvs is NULL if no special features are supported, and peer
sets `next_to_send` anyway:

```
0x5ed1c6719538 peer_reconnect
channeld/channeld.c:5205
0x5ed1c6719dab init_channel
channeld/channeld.c:5959
0x5ed1c6719f04 main
channeld/channeld.c:6005
```

Backport: v24.08
Fixes: https://github.com/ElementsProject/lightning/issues/7486
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-09-07 13:55:45 +02:00
evansmj
873e8b4ef8 docs: clarify writing-json-schemas.md and autogenerate-rpc-examples.py
Spelling and clarity on how to update schemas when adding RPCs.
2024-09-05 17:01:04 -07:00
ShahanaFarooqui
66d4d0f8fc doc: After release instructions update
- Updated `release-checklist` with new GitHub actions for Docker and PyPI publishing.
- Updated `repro` with information about the `cl-repro.sh` script.

Changelog-None.
2024-09-05 16:28:31 -07:00
Jesse de Wit
15eb1e6ff5 cln-tracer: readme usage clarifications 2024-09-05 15:49:03 -07:00
ShahanaFarooqui
1a71e15cf3 github: Read tag on HEAD in Github Actions
Running `git describe` in local setup correctly identifies the tag available on the tag. But `docker buildx` via actions does not identify it without `--tags` param.

Reference Issue: https://github.com/ElementsProject/lightning/issues/7626

Changelog-Fixed: Docker image created via github actions correctly reads the tag available on the HEAD.
2024-09-05 12:31:49 -07:00
ShahanaFarooqui
ad37328600 docker: git reset to avoid modded suffix
Changelog-Fixed: Core lightning's version will not be suffixed with -modded anymore.
2024-09-05 12:31:49 -07:00
ShahanaFarooqui
bb72ad39b1 github: Actions trigger of tag push
Changelog-Fixed: Regex expression for github actions tags push trigger.
2024-09-05 12:31:49 -07:00
ShahanaFarooqui
84b3e80d16 test: testplugpass requirements.txt updated to install local pyln-client
Python was installing `pyln-client` directly from the server for testplugpass plugin. This commit is updating the requirements.txt file to install pyln-client with absolute local path.
2024-09-03 23:24:12 -07:00
Rusty Russell
46fe1d34e6 pyln-client: try to bump version
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-09-03 23:24:12 -07:00
Rusty Russell
dc32e2c0dc pyln-client: don't refer to now-non-existent long_desc member.
This breaks reckless:

```
[2024-09-01 12:24:14,755] DEBUG:       doc = method.long_desc if method.long_desc is not None else "No documentation found"\n[2024-09-01 12:24:14,755] DEBUG:                                 ^^^^^^^^^^^^^^^^\n[2024-09-01 12:24:14,755] DEBUG:   AttributeError: \'Method\' object has no attribute \'long_desc\'\n[2024-09-01 12:24:14,755] ERROR: plugin testing failed\n[2024-09-01 12:24:14,770] WARNING: testplugpass: installation aborted\n'
```

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-09-03 23:24:12 -07:00
ShahanaFarooqui
5ec5580a58 meta: update changelog for v24.08
Changelog-None
2024-08-28 21:49:21 -07:00
ShahanaFarooqui
6c25d2095c docker: Cleaned up Dockerfile's Core Lightning installation
With PR #7618, Core Lightning installation with relative paths has been fixed and can be used again.

Changelog-None.
2024-08-28 17:31:40 -07:00
Rusty Russell
624d8b79f7 lightningd: fix up installs in subdirectories.
Commit a1fdeee76b "Makefile: clean up install path handling."
broke the ability to configure with one path and then run in a
different path.  Turns out people actually do this!  So, we have
to use relative paths, compared to our existing binary.

And we can't use path_rel, because that requires that the path
exist (thanks @Lagrang3!).

Fixes: https://github.com/ElementsProject/lightning/issues/7595
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-08-29 08:14:16 +09:30
ShahanaFarooqui
48fa438b15 script: Updating SHASUMS for updated zlib1g-dev in Ubuntu Noble
Changelog-Fixed: core lightning's reproducible build for Ubuntu v24.04 (noble).
2024-08-26 17:10:22 -07:00
ShahanaFarooqui
c9552e4228 meta: Update changelog for 24.08rc3
Release candidate 3 for v24.08
2024-08-26 11:53:42 -07:00
Rusty Russell
9d88ce3b59 pytest: suppress failing renepay test for Liquid.
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-08-23 18:52:15 +09:30
Rusty Russell
50949b7b9c askrene: hack in some padding so we don't overflow capacities.
Of course, we still will, since spendable is for a single HTLC, but
this also shows why we should treat *minimum* as the incorrect answer
if they cross, too.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
Fixes: https://github.com/ElementsProject/lightning/issues/7563
2024-08-23 18:52:15 +09:30
Rusty Russell
fafda82d82 askrene: fix up our handling of htlc_max.
It seems we didn't handle it correctly: we need to cap the first
segment as well as the others, as far as I can tell.

Also, it can be less than the maximum capacity.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-08-23 18:52:15 +09:30
Rusty Russell
975326ab5d askrene: round capacity *down* when converting to fp16.
Conversion is lossy, and we don't want to spend more than the channel,
so it's conservative to round down here.

This doesn't actually help our test though!

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-08-23 18:52:15 +09:30
Rusty Russell
af011f9dac pytest: make spendable test for askrene work properly, give a better name.
Based on great test case from https://github.com/daywalker90

```
E       AssertionError: assert {'107x2x0/1': 'Path total 285720859 > spendable 285718000', '108x1x0/1': 'Path total 384721849 > spendable 384718000'} == {}
E         Left contains 2 more items:
E         {'107x2x0/1': 'Path total 285720859 > spendable 285718000',
E          '108x1x0/1': 'Path total 384721849 > spendable 384718000'}
E         Full diff:
E           {
E         -  ,
E         +  '107x2x0/1': 'Path total 285720859 > spendable 285718000',
E         +  '108x1x0/1': 'Path total 384721849 > spendable 384718000',
E           }
```

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-08-23 18:52:15 +09:30
ShahanaFarooqui
4e309dc478 docs: Added info for NFS version
Changelog-None.
2024-08-22 11:52:19 -07:00
ShahanaFarooqui
382b496c5f github: Update FreeBSD Test
- Passing bitcoind version from matrix

- cleanup: Removed extra tabs and `-` from pypi.yml

Changelog-Fixed: Github action for FreeBSD setup
2024-08-22 20:42:29 +09:30
ShahanaFarooqui
3a4dd5f032 github: Update Github actions for Pypi publishing
Changelog-Fixed: Fixed the already existing Pypi publishing actions file.
2024-08-21 10:06:49 -07:00
ShahanaFarooqui
dadf9a78e2 docker: Fix for cryptography v42 upgrade
- **Poetry Issue:** The Docker build for `linux/arm/v7` failed in recent RC releases on the Poetry installation step in the `builder-python` stage. This issue occurred because the `builder-python` stage builds on target's arch but poetry was unable to install on arm/v7 without rust >= v1.56.1.
    - **Solution:** Instead of installing poetry on the `builder-python` stage, we leveraged the existing multi-arch `builder` stage, which already had Poetry. Now, we export the dependencies from `pyproject.toml` to `requirements.txt` within the `builder` stage and then copy `requirements.txt` to the `builder-python` stage for pip installation.

- **Cryptography installation Issue:** python installations for `pyln-proto` started failing due to Cryptography upgrade from v41 to v42 (#7475). It is because now Cryptography needs cargo/rust also.
    - **Solution:** Installing cargo in `builder-python` stage also.

- **Configure Prefix Issue:** Previously, we used `RUN ./configure --prefix=/tmp/lightning_install --enable-static` in the `builder` image and then copied `/tmp/lightning_install` from the `builder` stage to `/usr/local` in the `final` stage. However, this approach is now causing errors due to missing binaries/plugins at their default locations.
    - **Solution:** We are now configuring the installation to use the default location (`/usr/local`). To prevent the local image size from increasing by up to 87MB, instead of copying the entire `/usr/local/` directory, we are explicitly copying only the core lightning binaries.

Changelog-Fixed: Fixes failing Docker build for `arm32` arch.
2024-08-20 21:25:07 -07:00
ShahanaFarooqui
5d1b5b5faa docker: GitHub actions testing for docker release
- Temporarily adding `rc` tag trigger for testing `Build and push multi-platform docker images` action flow before the final release.

- Added some variable inputs for testing like repo, platforms, etc.

- Added more logs for future debugging.
2024-08-20 21:25:07 -07:00
Rusty Russell
76ef283b02 lightningd: fix another trivial memleak when running installed version.
```
**BROKEN** lightningd: MEMLEAK: 0x55ff8e8ec268
**BROKEN** lightningd:   label=char[]
**BROKEN** lightningd:   alloc:
**BROKEN** lightningd:     ccan/ccan/tal/tal.c:488 (tal_alloc_)
**BROKEN** lightningd:     ccan/ccan/tal/tal.c:517 (tal_alloc_arr_)
**BROKEN** lightningd:     ccan/ccan/tal/str/str.c:81 (tal_vfmt_)
**BROKEN** lightningd:     ccan/ccan/tal/str/str.c:37 (tal_fmt_)
**BROKEN** lightningd:     lightningd/lightningd.c:557 (find_subdaemons_and_plugins)
**BROKEN** lightningd:     lightningd/lightningd.c:1196 (main)
**BROKEN** lightningd:   parents:
**BROKEN** lightningd:     struct plugins
```

Changelog-None: Introduced this release.
Fixes: https://github.com/ElementsProject/lightning/issues/7590
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-08-20 18:51:39 -07:00
ShahanaFarooqui
203500d6f0 git: Update PR template
Changelog-None.
2024-08-19 16:00:41 -07:00
Rusty Russell
b99fd02393 pytest: add spendable tests for askrene.
Make sure we're not exceeding the spendable amount of a local channel.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-08-19 10:12:51 -07:00
Rusty Russell
7fb7234da1 askrene: change finalcltv to final_cltv, and return it in response.
You need to know it to make an onion, and in theory if we decided to
fuzz it could be different for different paths.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-08-19 10:12:51 -07:00
Rusty Russell
96f3637184 doc: note that getroutes return is different than getroute.
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-08-19 10:12:51 -07:00
Lagrang3
62a86cc47f renepay: add daywalker90's test case
Signed-off-by: Lagrang3 <lagrang3@protonmail.com>
2024-08-19 10:11:35 -07:00
Lagrang3
5400989552 renepay: bugfix: apply channel filter globally
Channel filter must apply to the modified gossmap+localmods,
otherwise we disable local channels with htlcmax=0.

Signed-off-by: Lagrang3 <lagrang3@protonmail.com>
2024-08-19 10:11:35 -07:00
Lagrang3
4fdc74f100 renepay: take it easy with local channels
Add a little bit of uncertainty to the local channels to avoid
consuming precisely all spendable_msat on our side, which leads to
temporary channel failure if the spendable_msat changes during the
course of the payment.

Signed-off-by: Lagrang3 <lagrang3@protonmail.com>
2024-08-19 10:11:35 -07:00
Lagrang3
e41625fb29 renepay: bugfix refreshgossmap
Refresh gossmap once before we read the routehints.
Make sure that if channels in the routehints are public,
we retrieve their capacities from gossip.

Signed-off-by: Lagrang3 <lagrang3@protonmail.com>
2024-08-19 10:11:35 -07:00
Lagrang3
d39b0092ec renepay: bugfix reserved htlc in MCF
Reserved HTLCs were underestimated by floor (mathematical function)
use ceil instead.

Signed-off-by: Lagrang3 <lagrang3@protonmail.com>
2024-08-19 10:11:35 -07:00
Lagrang3
bb68e65b7a renepay: add precondition check + error msg
- add more checks
- add more error messages
- compute probabilities without fees during MCF
- compute probabilities with fees during get_routes

Signed-off-by: Lagrang3 <lagrang3@protonmail.com>
2024-08-19 10:11:35 -07:00
Lagrang3
684d6dff50 renepay: patch to assertion htlc_total<=known_max
In theory we should not have htlc_total<=known_max.
But for some strange race condition we do sometimes.
Until we find a solution to ensure the correct state
of the uncertainty network we remove the assertion.
Thanks to signed arithmetic and MIN guards, the rest
of the code in linearize_channel can handle the
weird cases with known_max<htlc_total.

Signed-off-by: Lagrang3 <lagrang3@protonmail.com>
2024-08-19 10:11:35 -07:00
ShahanaFarooqui
680f81f2aa Adding PR Template 2024-08-19 04:16:42 -07:00
ShahanaFarooqui
52f9678deb meta: Update changelog for 24.08rc2
Release candidate 2 for v24.08
2024-08-15 21:20:35 -07:00
Rusty Russell
9a6325c4f3 doc: properly document sub-subobject fields.
Inside listpeerchannels, there's an object called `updates`, and inside that objects `local` and `remote`.  We flatten this, but the documentation doesn't mention the `updates` field at all.

Ideally we would rename these fields to include `updates_` but that would be a breaking change.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>

```
     - `row` (reference to `peerchannels_channel_type.rowid`, sqltype `INTEGER`)
     - `arrindex` (index within array, sqltype `INTEGER`)
     - `names` (type `string`, sqltype `TEXT`)
-  - `local_htlc_minimum_msat` (type `msat`, sqltype `INTEGER`, from JSON object `local`)
-  - `local_htlc_maximum_msat` (type `msat`, sqltype `INTEGER`, from JSON object `local`)
-  - `local_cltv_expiry_delta` (type `u32`, sqltype `INTEGER`, from JSON object `local`)
-  - `local_fee_base_msat` (type `msat`, sqltype `INTEGER`, from JSON object `local`)
-  - `local_fee_proportional_millionths` (type `u32`, sqltype `INTEGER`, from JSON object `local`)
-  - `remote_htlc_minimum_msat` (type `msat`, sqltype `INTEGER`, from JSON object `remote`)
-  - `remote_htlc_maximum_msat` (type `msat`, sqltype `INTEGER`, from JSON object `remote`)
-  - `remote_cltv_expiry_delta` (type `u32`, sqltype `INTEGER`, from JSON object `remote`)
-  - `remote_fee_base_msat` (type `msat`, sqltype `INTEGER`, from JSON object `remote`)
-  - `remote_fee_proportional_millionths` (type `u32`, sqltype `INTEGER`, from JSON object `remote`)
+  - `local_htlc_minimum_msat` (type `msat`, sqltype `INTEGER`, from JSON object `updates.local`)
+  - `local_htlc_maximum_msat` (type `msat`, sqltype `INTEGER`, from JSON object `updates.local`)
+  - `local_cltv_expiry_delta` (type `u32`, sqltype `INTEGER`, from JSON object `updates.local`)
+  - `local_fee_base_msat` (type `msat`, sqltype `INTEGER`, from JSON object `updates.local`)
+  - `local_fee_proportional_millionths` (type `u32`, sqltype `INTEGER`, from JSON object `updates.local`)
+  - `remote_htlc_minimum_msat` (type `msat`, sqltype `INTEGER`, from JSON object `updates.remote`)
+  - `remote_htlc_maximum_msat` (type `msat`, sqltype `INTEGER`, from JSON object `updates.remote`)
+  - `remote_cltv_expiry_delta` (type `u32`, sqltype `INTEGER`, from JSON object `updates.remote`)
+  - `remote_fee_base_msat` (type `msat`, sqltype `INTEGER`, from JSON object `updates.remote`)
+  - `remote_fee_proportional_millionths` (type `u32`, sqltype `INTEGER`, from JSON object `updates.remote`)
   - `ignore_fee_limits` (type `boolean`, sqltype `INTEGER`)
   - `lost_state` (type `boolean`, sqltype `INTEGER`)
   - `feerate_perkw` (type `u32`, sqltype `INTEGER`, from JSON object `feerate`)
```
2024-08-16 07:19:52 +09:30
Rusty Russell
054eeb8aa2 plugins/sql: fix crash when subobject is missing which has subobject inside it.
There's only one place (added in v24.02) where we have nested subobjects, and
if the outer sub-object is not there it crashes.

```
sql: FATAL SIGNAL 11 (version v24.08rc1-2-ge134f2f-modded)
0x5781d447239b send_backtrace
        common/daemon.c:33
0x5781d4472432 crashdump
        common/daemon.c:75
0x787bcd64531f ???
        ./signal/../sysdeps/unix/sysv/linux/x86_64/libc_sigaction.c:0
0x5781d447782a json_get_membern
        common/json_parse_simple.c:210
0x5781d44778cc json_get_member
        common/json_parse_simple.c:223
0x5781d445d0e2 process_json_obj
        plugins/sql.c:537
0x5781d445d10d process_json_obj
        plugins/sql.c:538
0x5781d445d598 process_json_list
        plugins/sql.c:684
0x5781d445d65a process_json_result
        plugins/sql.c:699
0x5781d445d7cb default_list_done
        plugins/sql.c:722
0x5781d446349d handle_rpc_reply
        plugins/libplugin.c:1016
0x5781d4463640 rpc_read_response_one
        plugins/libplugin.c:1202
0x5781d44636f1 rpc_conn_read_response
        plugins/libplugin.c:1226
0x5781d459e56c next_plan
        ccan/ccan/io/io.c:60
0x5781d459ea3d do_plan
        ccan/ccan/io/io.c:422
0x5781d459eafa io_ready
        ccan/ccan/io/io.c:439
0x5781d45a0469 io_loop
        ccan/ccan/io/poll.c:455
0x5781d4463dcb plugin_main
        plugins/libplugin.c:2230
```

Changelog-Fixed: Plugins: `sql` crash on querying `listpeerchannels` during channel establishment.
Fixes: https://github.com/ElementsProject/lightning/issues/7505
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-08-16 07:19:52 +09:30
Rusty Russell
a6c2f183d6 bookkeeper: fix up out-of-order migrations in rc1
This was introduced in rc1, resulting in:

```
2024-08-15T01:33:48.343Z **BROKEN** plugin-bookkeeper: query failed: plugins/bkpr/recorder.c:738: SELECT  e.id, e.account_id, a.name, e.origin, e.tag, e.credit, e.debit, e.output_value, e.currency, e.timestamp, e.blockheight, e.utxo_txid, e.outnum, e.spending_txid, e.payment_id, e.ignored, e.stealable, e.ev_desc, e.spliced FROM chain_events e LEFT OUTER JOIN accounts a ON e.account_id = a.id WHERE  e.spending_txid = ? AND e.account_id = ? AND e.utxo_txid = ? AND e.outnum = ?
```

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-08-16 07:18:29 +09:30
ShahanaFarooqui
be5ad3d7a9 docker: Docker file fixes for reproducible builds
- Added missing mako and grpcio-tools for ubuntu distro Docker files

- Fixed incorrect bitcoincore link

Changelog-Fixed: Fedora, focal, jammy & noble's failing reproducible builds are fixed now.
2024-08-15 16:47:45 +09:30
Lagrang3
7056018b15 renepay: add const probability cost
The probability for a success forward of x amount on a channel is now
computed as:

	P_success(x) = b * P_rene(x)

where P_rene(x) is the probability distribution proposed by Rene
Pickhardt with a uniform distribution on the known liquidity of the
channel and 'b' is a new parameter we add in this PR, by the name of
"base probability". The "base probability" represents the probability
for a channel in the network choosen at random to be able to forward at
least 1msat, ie. of being alive, non-depleted and with at least one HTLC
slot. We don't know the value of 'b', but for the moment we assume that
it is 0.98 and use that as default.

As a consequence the probability cost becomes non-linear and non-convex
because of the additional constant term:

	Cost(x) = - log P_success(x)
	        = - log b  -  - log P_rene(x)
		= - log b  +  Cost_rene(x)

We currently don't handle well base fees and neither this additional
"base probability" but we can as a first approximation linearize the
cost function in this way:

	Cost_linear(x) = (- log b)*x  +  Cost_rene_linear(x)

Changelog-Added: renepay: Add a dev parameter to renepay that represents
a constant probability of availability for all channels in the network.

Signed-off-by: Lagrang3 <lagrang3@protonmail.com>
2024-08-15 16:46:41 +09:30
Rusty Russell
395781f204 pyln-testing: fix catching of memleak/broken errors at exit.
Commit 901342b50d ("pyln-testing: require
explicit pattern for BROKEN messages.") changed to a manual scan of
logs rather than using is_in_log, so it needs to manually refresh,
otherwise we miss final log messages.

This causes us to often miss memleak messages, which are printed
only in the exit path!

Reported-by: Lagrang3
Fixes: https://github.com/ElementsProject/lightning/issues/7565
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-08-15 16:38:12 +09:30
Rusty Russell
e2ec60a369 pytest: handle more expected broken messages.
Once we fix our broken log detection, we find some we were missing.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-08-15 16:38:12 +09:30
Rusty Russell
d29933b7c2 lightningd: fix trivial memleak.
Mainly, it just causes complaints if we're running a lightningd which is installed
(in which case, my_path is not stolen, unlike running locally installed).

Reported-by: daywalker90
Fixes: https://github.com/ElementsProject/lightning/issues/7569
Changelog-None: regression this release
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-08-14 11:50:42 -07:00
ShahanaFarooqui
fb3579c1a4 meta: Update changelog for 24.08rc1
Release candidate 1 for v24.08
2024-08-13 08:32:23 -07:00
ShahanaFarooqui
d493320147 devtools: Fixed changlog.py default commit range 2024-08-13 08:32:23 -07:00
ShahanaFarooqui
3fe454b54e gitignore: Add missing gitignore plugins an devtools 2024-08-13 08:32:23 -07:00
Rusty Russell
a2b0212d50 lightningd: handle duplicate watches on the same thing correctly.
Our hash tables allow duplicate keys, and we use that in a few places.
However, the get() function only returns the first, so it's not a good
idea with such hash tables.

Another patch fixes this at a deeper level (using different hash table
types depending on whether this table can have duplicates), but this
is the minimal fix for existing code.

This may be the cause behind us occasionally missing onchain events:

Fixes: https://github.com/ElementsProject/lightning/issues/7460
Fixes: https://github.com/ElementsProject/lightning/issues/7377
Fixes: https://github.com/ElementsProject/lightning/issues/7118
Fixes: https://github.com/ElementsProject/lightning/issues/6951

This fixes them in future: fixing them now will require something else.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
Changelog-Fixed: lightningd: occasionally we could miss transaction outputs (not telling gossipd, or even onchaind)
2024-08-13 07:25:02 -07:00
Lagrang3
9afc10bf99 renepay: add cli option exclude
msggen cannot handle the complex type in renepay-exclude,
therefore I added a rule override for it, just like pay-exclude.

```
msggen cln-grpc/proto/node.proto
Traceback (most recent call last):
  File "/home/rusty/devel/cvs/lightning/contrib/msggen/msggen/__main__.py", line 131, in <module>
    main()
  File "/home/rusty/devel/cvs/lightning/contrib/msggen/msggen/__main__.py", line 115, in main
    run()
  File "/home/rusty/devel/cvs/lightning/contrib/msggen/msggen/__main__.py", line 72, in run
    service = load_jsonrpc_service(
              ^^^^^^^^^^^^^^^^^^^^^
  File "/home/rusty/devel/cvs/lightning/contrib/msggen/msggen/utils/utils.py", line 241, in load_jsonrpc_service
    methods = [load_jsonrpc_method(name) for name in grpc_method_names]
               ^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/rusty/devel/cvs/lightning/contrib/msggen/msggen/utils/utils.py", line 209, in load_jsonrpc_method
    request = CompositeField.from_js(schema["methods"][rpc_name]['request'], path=name)
              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/rusty/devel/cvs/lightning/contrib/msggen/msggen/model.py", line 297, in from_js
    field = ArrayField.from_js(fpath, ftype)
            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/rusty/devel/cvs/lightning/contrib/msggen/msggen/model.py", line 464, in from_js
    itemtype = UnionField.from_js(child_js, path)
               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/rusty/devel/cvs/lightning/contrib/msggen/msggen/model.py", line 393, in from_js
    itemtype = PrimitiveField(
               ^^^^^^^^^^^^^^^
TypeError: PrimitiveField.__init__() missing 2 required positional arguments: 'added' and 'deprecated'
```

Signed-off-by: Lagrang3 <lagrang3@protonmail.com>
Changelog-EXPERIMENTAL: renepay: add cli option "exclude" to manually disable channels and nodes.
2024-08-12 22:44:58 -07:00
Lagrang3
44d53dc473 renepay: add a channel filtering paymod
We add a channel filtering paymod that disables channels that have very
low max_htlc. It can be expanded to consider other properties as well,
for instance high base fee, low capacity or high latency.

Changelog-Added: renepay: prune the network by disabling channels we
don't like, eg. very low max_htlc.

Signed-off-by: Lagrang3 <lagrang3@protonmail.com>
2024-08-12 22:44:58 -07:00
Lagrang3
c0dd3cd826 renepay: disabled channels in a map
Expecting to have more than just a bunch of disabled channels if we
prune the lightning network heavily I am changing the internal data
structure of disabledmap from a simple array to a hashtable.

Have a finer control over disabled channels by targeting
short_channel_id_dir instead of short_channel_id,
ie. we can disable a single direction of a channel.

Signed-off-by: Lagrang3 <lagrang3@protonmail.com>
2024-08-12 22:44:58 -07:00
daywalker90
7ffd0a3936 cln-plugin: add multi options for String and i64
Changelog-Added: cln-plugin: add multi options for String and i64
2024-08-13 12:24:45 +09:30
Alex Myers
88504ea6d2 reckless-rpc: catch failed reckless subprocess
... before processing the output. It's probably a python backtrace, not
json anyway.
2024-08-12 18:10:45 -07:00
Alex Myers
1cb478d2c7 reckless-rpc: catch failed json parsing of reckless output 2024-08-12 18:10:45 -07:00
Alex Myers
ab7a63ec99 reckless-rpc: add documentation 2024-08-12 18:10:45 -07:00
Alex Myers
2567a116b1 reckless-rpc: catch old installed version
If the rpc plugin is run while an older version of reckless is found on
PATH, it produces an error:

2024-08-01T18:32:00.849Z DEBUG   plugin-recklessrpc: reckless-stderr:usage: reckless [-h] [-d RECKLESS_DIR] [-l LIGHTNING] [-c CONF] [-r] [--network NETWORK] [-v]
{install,uninstall,search,enable,disable,source,help} ...
reckless: error: unrecognized arguments: --json

Catch this and don't try to parse the output as json.
2024-08-12 18:10:45 -07:00
Alex Myers
f93ec36f8a reckless-rpc: accept and pass generic subcommands
This allows generic subcommands to be passed to reckless-rpc along with
the target to search/install/etc..  These commands are unvalidated so
far and may crash the reckless process.

Changelog-Added: reckless-rpc plugin: issue commands to reckless over rpc.
2024-08-12 18:10:45 -07:00
Alex Myers
9eb5359eb0 reckless-rpc: auto-accept reckless config creation dialog
This would interupt most commands during the config reading
step until the user accepts the prompt to create a new empty
config.
2024-08-12 18:10:45 -07:00
Alex Myers
1d9ff8b022 reckless-rpc: read lightningdir and network from listconfigs 2024-08-12 18:10:45 -07:00
Alex Myers
f69c4d6385 reckless-rpc: initial boilerplate
Trying a single command first - reckless-search to test
launching a reckless process and processing the result.
2024-08-12 18:10:45 -07:00
Lagrang3
5073942eef askrene: memleak: scan reserved htable
Signed-off-by: Lagrang3 <lagrang3@protonmail.com>
2024-08-13 09:12:40 +09:30
Lagrang3
cf3375c701 askrene: change reserve_hash for reserve_htable
Signed-off-by: Lagrang3 <lagrang3@protonmail.com>
2024-08-13 09:12:40 +09:30
Rusty Russell
4f49143f24 openingd: don't ask for scid_alias in channel type if remote doesn't tell us they support it.
This is actually totally fair, and LND, which does not support it without an option, rejects.

Thanks to Vincenzo and roasbeef for debugging this for me!

Fixes: https://github.com/ElementsProject/lightning/issues/7221
Changelog-Fixed: Protocol: we can now open unannounced channels with LND nodes again.
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-08-12 16:02:31 -07:00
Lagrang3
4ac85b2cd1 askrene: inform-channel fixes argument order
The documentation and the implementation of inform-channel have
different orders for the arguments minimum_msat and maximum_msat.
We change the order in the documentation to match that of the
implementation: minimum_msat comes before maximum_msat.

Signed-off-by: Lagrang3 <lagrang3@protonmail.com>
2024-08-12 14:17:22 -07:00
Lagrang3
3f32f9ea10 renepay: fix strange gossmap_refresh log
Often I find this in the logs:
DEBUG   plugin-cln-renepay: gossmap ignored 94692259263600 channel updates

Apparently gossmap_refresh does not initialize the input variable num_channel_updates_rejected.
Fix this by explicitely initializing it before calling gossmap_refresh.

Signed-off-by: Lagrang3 <lagrang3@protonmail.com>
2024-08-12 13:27:34 -07:00
Lagrang3
5e4eb7bdc3 renepay: fix double free of tal object
routefail object allocation was linked to route,
we had a crash of the plugin with the following error:

0x561f424fc07a send_backtrace
	common/daemon.c:33
0x561f424fc102 crashdump
	common/daemon.c:75
0x7f5b0e7dc04f ???
	???:0
0x7f5b0e82ae2c ???
	???:0
0x7f5b0e7dbfb1 ???
	???:0
0x7f5b0e7c6471 ???
	???:0
0x561f4252581f call_error
	ccan/ccan/tal/tal.c:95
0x561f425258c8 check_bounds
	ccan/ccan/tal/tal.c:169
0x561f425258f9 to_tal_hdr
	ccan/ccan/tal/tal.c:179
0x561f42526283 tal_free
	ccan/ccan/tal/tal.c:525
0x561f424e5379 routefail_end
	plugins/renepay/routefail.c:52
0x561f424e557b handle_failure
	plugins/renepay/routefail.c:431

apparently there was a race condition for which the route was first
freed before we arrived to routefail_end where we manually free
routefail. I don't see how this could have happened, but anyways
this subtle bug can be avoided by linking the routefail to the payment.

Signed-off-by: Lagrang3 <lagrang3@protonmail.com>
2024-08-12 13:27:34 -07:00
Lagrang3
c4d0447773 renepay: remove __PRETTY_FUNCTION__
Remove __PRETTY_FUNCTION__ in favor of __func__

Signed-off-by: Lagrang3 <lagrang3@protonmail.com>
2024-08-12 13:27:34 -07:00
Lagrang3
cc9b8b0a19 renepay: bugfix finalized routes
Changelog-Fixed: renepay: finalized routes have to be processed and
determine the payment status even after the payment goes into the
background (no current command active). Not doing so leads to finalized
routes getting stuck in the payment internal data structure and their
associated HTLCs in the uncertainty network don't get released.

Signed-off-by: Lagrang3 <lagrang3@protonmail.com>
2024-08-12 13:27:34 -07:00
Lagrang3
04bf0ae29d renepay: remove unnecessary payment list
We rather have a payment hash table to look up payments based on the
payment hash than having a list.

Signed-off-by: Lagrang3 <lagrang3@protonmail.com>
2024-08-12 13:27:34 -07:00
Lagrang3
6a1776d312 renepay: rm HTLCs from uncertainty on route free
Add remove_htlc in the route destructor.

Signed-off-by: Lagrang3 <lagrang3@protonmail.com>
2024-08-12 13:27:34 -07:00
Lagrang3
d6667e305b renepay: review routetracking
Add missing uncertainty update after payment success.

Signed-off-by: Lagrang3 <lagrang3@protonmail.com>
2024-08-12 13:27:34 -07:00
Lagrang3
ccb70de4eb renepay: minor fix
Use success_data_from_listsendpays to check if there are "complete"
sendpays instead of imposing the presence of "complete" sendpays as a
precondition for success_data_from_listsendpays.

Signed-off-by: Lagrang3 <lagrang3@protonmail.com>
2024-08-12 13:27:34 -07:00
Lagrang3
0c685f541e renepay: rethink the computed routes storage
Simply move the "computed routes" array from the payment to the
routetracker. It makes sense to put all temporary stages of routing into
a single data structure: the routetracker.

Signed-off-by: Lagrang3 <lagrang3@protonmail.com>
2024-08-12 13:27:34 -07:00
Lagrang3
1052945ac0 renepay: remove unnecessary rpc calls
There were some dummy rpc calls to waitblockheight in the payment workflow
to allow the function stack to clear. But it is better if some steps in
the payment are executed "atomically" to avoid strange race conditions.
For example: all steps between getting pending sendpays, computing new
routes and sending those routes.

Signed-off-by: Lagrang3 <lagrang3@protonmail.com>
2024-08-12 13:27:34 -07:00
Lagrang3
a339e553e8 renepay: listsendpay before computing routes
It feels unsafe to rely on the internal state of the plugin's database
to tell how many pending sendpays there are for the current payment.
The safest way is to assume lightningd knows and thus use listsendpay
before computing routes.

Signed-off-by: Lagrang3 <lagrang3@protonmail.com>
2024-08-12 13:27:34 -07:00
Lagrang3
ec431276ac renepay: global record of computed routes
Use a single global map of computed routes instead of one for each
payment.

Signed-off-by: Lagrang3 <lagrang3@protonmail.com>
2024-08-12 13:27:34 -07:00
Lagrang3
8b2d45e52e renepay: simpler routetracker
- remove payment pointer from routetracker, fetch payment if necessary
  from payment_hash;
- "have results" condition as a function call to routetracker.

Signed-off-by: Lagrang3 <lagrang3@protonmail.com>
2024-08-12 13:27:34 -07:00
Lagrang3
f16363b86d renepay: small tweak to decay time
The time of decay "TIMER_FORGET_SEC" was set to 1 hour,
which is very low, it would make the plugin try depleted channels after
just a couple of seconds for very small amounts.
I set it to 1 week ~ 6e5 seconds.

Signed-off-by: Lagrang3 <lagrang3@protonmail.com>
2024-08-12 13:17:21 -07:00
Lagrang3
5ef5739e27 askrene: reserve: fix assertion
Fixes bad guide for json_scan.

Signed-off-by: Lagrang3 <lagrang3@protonmail.com>
2024-08-12 13:17:09 -07:00
michael1011
d32433a553 bkpr: add payment_id parameter to listaccountevents to filter events.
When you have *lots* of events in your bkpr database looking up a
specific event via calling bkpr-listaccountevents and using jq or
grep to filter gets very slow (and wasteful of CPU and disk resources).
This commit adds the paremeter payment_id to the call to filter for a
specific payment id via a where clause in the request to the database of bkpr.

Changelog-Added: Plugins: Add payment_id parameter to bkpr-listaccountevents to filter events.
2024-08-12 10:22:55 -07:00
michael1011
406d6a6e22 bkpr: minor clarification in comment. 2024-08-12 10:22:55 -07:00
Rusty Russell
a243f3c79c plugin/pay: fix crash if failcodename isn't set.
Fixes: https://github.com/ElementsProject/lightning/issues/7200
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-08-12 18:36:11 +09:30
Rusty Russell
48259afb70 lightningd: always broadcast our own gossip when it changes.
When a peer connects, we always send all our own gossip (even if they
had set the timestamp filters to filter it out).  But we weren't
forcing it out to them when it changed, so this logic only applied to
unstable or frequently-restarting nodes.

So now, we tell all the peers whenever we tell gossipd about our new
gossip.

Fixes: #7276
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
Changelog-Changed: Protocol: We now send current peers our changed gossip (even if they set timestamp_filter otherwise), not just on reconnect.
2024-08-12 16:30:29 +09:30
Rusty Russell
b525207e5c lightningd: track whether we're supposed to be throttling gossip.
We're going to need this for the next commit.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-08-12 16:30:29 +09:30
Rusty Russell
4886d228e7 pytest: test that we inform all peers about gossip changes.
In particular, those who've filtered it out.

This currently fails, as expected.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-08-12 16:30:29 +09:30
Rusty Russell
2d129e79ab pytest: enhance test_gossip_pruning
We didn't actually check that we *send* the refreshed gossip, just
that we print the message saying we're going to.

So check that everyone received updated gossip when this happens.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-08-12 16:30:29 +09:30
Rusty Russell
975dd76086 lightningd: create new return code for enableoffer.
Suggested-by: https://github.com/Lagrang3
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-08-11 11:27:10 +09:30
Vincenzo Palazzo
1e1edfd073 offer: allow re-enabling a previously disabled offer
Sometimes, for various reasons, a user disables an offer
and then wants to re-enable it. This should be allowed because,
from the CLN point of view, it is just an internal state.

If a user has constraints on the description of the invoice
because they are using services that link some sort of user ID
to an offer, it is important for the user to be able to re-enable the
offer, not create a new one. Creating a new offer would
require a different description.

Link: https://github.com/ElementsProject/lightning/issues/7360
Co-Developed-by: Rusty Russell <rusty@rustcorp.com.au>
Signed-off-by: Vincenzo Palazzo <vincenzopalazzodev@gmail.com>
2024-08-11 11:27:10 +09:30
ShahanaFarooqui
47e7127b19 doc: Instructions to use the script for generating examples
Changelog-Added: doc: all examples in the documentation are now generated from running the code, so they are current.
2024-08-09 23:56:45 -07:00
ShahanaFarooqui
f92a4ccea5 doc: Updated json examples in schema files 2024-08-09 23:56:45 -07:00
ShahanaFarooqui
50faa7c122 script: Auto generate rpc examples for documentation
I will commit doc/schemas/lightning-*.json files separately to keep this commit easier to review.

- test-autogenerate-rpc-examples updates all example request & responses in doc/schemas/lightning-*.json files.

- Updated tools/fromschema.py to accommodate the sql JSON example requirement where it does not accept -o in the query but shell does (for queries containing the = sign).

Changelog-None.
2024-08-09 23:56:45 -07:00
ShahanaFarooqui
fe7981bda2 pyln-testing: Increasing bitcoin rpc threads from default 4 to 20
Bitcoind's web server has a default of 4 threads, with queue depth 16 and it fails rather than queue beyond that.

Increasing thread count to 20 for running >10 lightning test nodes simultaneously.
2024-08-09 23:56:45 -07:00
ShahanaFarooqui
1ec508eb54 doc: Fixing schema definition
- `Notes` is not a required field in renepaystatus response
2024-08-09 23:56:45 -07:00
ShahanaFarooqui
9c0f073a44 tests: Removed non-essential hsm copy step 2024-08-09 23:56:45 -07:00
Rusty Russell
62f531a1f2 lightningd: configvar style fixes
1) We can't simply cast away const to manipulate a string, the compiler can assume
   we don't.  The type must be made non-const.
2) cisspace() is nicer to use than isspace() (no cast required!)
3) Simply place a NUL terminator instead of using memmove to set it.
4) Use cast_const to add const to char **, where necessary.
5) Add Changelog line, for CHANGELOG.md

Changelog-Fixed: Config: whitespace at the end of (most) options is now ignored, not complained about.
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-08-10 15:20:59 +09:30
Max Rantil
3e65ef4b12 lightningd: trim whitespaces from end of config parameters
Signed-off-by: Max Rantil <rantil@pm.me>
2024-08-10 15:20:59 +09:30
Rusty Russell
d0c0c4480a plugins: fix more uninitialized vars in bookkeeper.
Did a sweep to find any others, give this from sanitizer:

```
2024-08-09T18:06:45.1729472Z plugins/bkpr/recorder.c:2057:23: runtime error: load of value 190, which is not a valid value for type 'bool'
2024-08-09T18:06:45.1729877Z SUMMARY: UndefinedBehaviorSanitizer: undefined-behavior plugins/bkpr/recorder.c:2057:23 in
```

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-08-10 12:21:39 +09:30
Rusty Russell
359f1b8a30 bookkeeper: fix uninitialized variable.
Valgrind found this.  I think two PRs were added in parallel, which is why we
only found it after merge:

```
2024-08-09T01:57:23.7375752Z ==34263== Uninitialised byte(s) found during client check request
2024-08-09T01:57:23.7376275Z ==34263==    at 0x172405: memcheck_ (mem.h:247)
2024-08-09T01:57:23.7376661Z ==34263==    by 0x172585: db_bind_int (bindings.c:49)
2024-08-09T01:57:23.7377086Z ==34263==    by 0x126233: log_chain_event (recorder.c:2057)
2024-08-09T01:57:23.7377544Z ==34263==    by 0x11BF8B: json_utxo_deposit (bookkeeper.c:1735)
2024-08-09T01:57:23.7378207Z ==34263==    by 0x12BED3: ld_command_handle (libplugin.c:1847)
2024-08-09T01:57:23.7378674Z ==34263==    by 0x12C649: ld_read_json_one (libplugin.c:1998)
2024-08-09T01:57:23.7379114Z ==34263==    by 0x12C780: ld_read_json (libplugin.c:2018)
2024-08-09T01:57:23.7379534Z ==34263==    by 0x2990CB: next_plan (io.c:60)
2024-08-09T01:57:23.7379881Z ==34263==    by 0x299D21: do_plan (io.c:422)
2024-08-09T01:57:23.7380230Z ==34263==    by 0x299D88: io_ready (io.c:439)
2024-08-09T01:57:23.7380585Z ==34263==    by 0x29C1BC: io_loop (poll.c:455)
2024-08-09T01:57:23.7380980Z ==34263==    by 0x12D439: plugin_main (libplugin.c:2230)
```

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-08-10 12:21:39 +09:30
Lagrang3
db4a26d94a renepay: remove unused declaration
Signed-off-by: Lagrang3 <lagrang3@protonmail.com>
2024-08-09 14:38:17 +09:30
Lagrang3
07d4451a40 renepay: bugfix reading pending sendpays
When renepay starts, one of the first operations it does is to check for
pending sendpays for the same invoice. Those are added up to an internal
database to keep track of. Also the amount they deliver to the
destination is computed so that the current payment rpc call would try
to complete the payment for whatever amount remains to pay.
For an incomplete payment after calling the RPC renepay I found this in
the logs:

2024-05-22T19:44:19.853Z DEBUG   plugin-cln-renepay: There are pending sendpays to this invoice. groupid = 6 delivering = 0msat, last_partid = 10

Where delivering should be the sum of the amounts delivered by pending routes.
2024-08-09 14:38:17 +09:30
Christian Decker
aa45e737dc libplugin: Add parser for channel_hint from JSON 2024-08-09 13:59:07 +09:30
Christian Decker
6a53cf288b libplugin: Add primitive to serialize channel_hint to JSON 2024-08-09 13:59:07 +09:30
Christian Decker
eae378c9d2 common: Add some more JSON primitives
We were missing the `short_channel_id_dir` helpers.
2024-08-09 13:59:07 +09:30
Christian Decker
8e9f71ff85 libplugin: pay now emits channel_hint as we learn about the net
The `pay` plugin, as well as other plugins making use of the tree-pay
executor, will now emit their observations as they see them. The
notifications are sent on the `channel_hint_updated` topic, and any
subscriber will get them.

We also added a `timestamp` to the `struct channel_hint`, as these
observations now outlive the `pay` call, and have to be attenuated /
relaxed as they age, until we can eliminate them completely (when the
restriction is equal to the structural information gathered from the
gossip).

Changelog-Added: pay: Payments now emit `channel_hint_updated` notification to share inferred balances and observations across multiple payments.
2024-08-09 13:59:07 +09:30
niftynei
0e99f2e718 bkpr: add two custom notifications that we listen for
It might be nice to let the bookkeeper keep track of external accounts
as well as the internal onchain wallet? To this end, we add some new
custom notifications, which the bookkeeper will ingest and add to its
ledger.

Suggested-By: @chrisguida

Changelog-Added: PLUGINS: `bookkeeper` now listens for two custom events: `utxo_deposit` and `utxo_spend`. This allows for 3rd party plugins to send onchain coin events to the `bookkeeper`.  See the new plugins/bkpr/README.md for details on how these work!
2024-08-09 10:21:44 +09:30
niftynei
cd4298de84 bugfix: node refuses to re-start after emergency recover
one of the fields in the database isn't read/accessed during stub
reinitialization, so my node crashes.

error:
Never accessed column last_sig in query SELECT  id, peer_id, scid, full_channel_id, channel_config_local, channel_config_remote, state, funder, channel_flags, require_confirm_inputs_local, require_confirm_inputs_remote, minimum_depth, next_index_local, next_index_remote, next_htlc_id, funding_tx_id, funding_tx_outnum, funding_satoshi, our_funding_satoshi, funding_locked_remote, push_msatoshi, msatoshi_local, fundingkey_remote, revocation_basepoint_remote, payment_basepoint_remote, htlc_basepoint_remote, delayed_payment_basepoint_remote, per_commit_remote, old_per_commit_remote, shachain_remote_id, shutdown_scriptpubkey_remote, shutdown_keyidx_local, last_sent_commit_state, last_sent_commit_id, last_tx, last_sig, last_was_revoke, first_blocknum, min_possible_feerate, max_possible_feerate, msatoshi_to_us_min, msatoshi_to_us_max, future_per_commitment_point, last_sent_commit, feerate_base, feerate_ppm, remote_upfront_shutdown_script, local_static_remotekey_start, remote_static_remotekey_start, channel_type, shutdown_scriptpubkey_local, closer, state_change_reason, revocation_basepoint_local, payment_basepoint_local, htlc_basepoint_local, delayed_payment_basepoint_local, funding_pubkey_local, shutdown_wrong_txid, shutdown_wrong_outnum, lease_expiry, lease_commit_sig, lease_chan_max_msat, lease_chan_max_ppt, htlc_minimum_msat, htlc_maximum_msat, alias_local, alias_remote, ignore_fee_limits, remote_feerate_base, remote_feerate_ppm, remote_cltv_expiry_delta, remote_htlc_minimum_msat, remote_htlc_maximum_msat, last_stable_connection FROM channels WHERE state != ?;
2024-08-08 17:11:38 -07:00
Christian Decker
8c14c39c7e onchaind: Adjust the sweep target deadline for fee estimation
We used to always target `now() + 300`, which ends up never really
confirming, as the fee estimate bumps into the min-relay-fee
limit. With this commit we set an absolute target of 2 weeks, and a
linear fee rampup, until we are at T-2h, at which point we just stick
with the estimate, and try with this increased feerate to try and get
the sweep confirmed.

This ought to make RBF transactions much more efficient for closing
channels.

Changelog-Fixed onchaind: The sweep deadline for to_us outputs would be reset on each restart of the subdaemon. Now the deadline is absolute in terms of the close height.
2024-08-09 09:08:06 +09:30
niftynei
46dcc6e031 bkpr: properly account for fees and channel closures if splice
We do some fancy accounting for channel closures; since we're tagging
splice txs as closes we need to mark them as splices so we can treat them
as any other 'normal' on chain event.
2024-08-08 12:30:53 -07:00
niftynei
7b3a4799db coin-moves: when a splice confirms, send a channel_closed event
We weren't properly notifying that a channel output has been spent in
the case of it being spent in a splice. This fixes the notification side
of the equation, however there's still some issues remaining for the
bookkeeper side (to come).

Changelog-Fixed: We now send a `coin_movement` notification for splice confirmations of channel funding outpoint spends.
2024-08-08 12:30:53 -07:00
Christian Decker
89f01f13fc pay: Use paymod_log when filtering routehints for changes
Changelog-Changed: pay: Improved logging should facilitate debugging considerably.
2024-08-08 12:20:44 -07:00
Christian Decker
44e5bbc8e5 pay: Log the invoice we are about to pay
Should make debugging based on logs a bit simpler.
2024-08-08 12:20:44 -07:00
Christian Decker
82afa8d38c pay: Add a pre-flight check for the spendable balance
Changelog-Added: pay: The pay plugin now checks whether we have enough spendable capacity before computing a route, returning a clear error message if we don't
2024-08-08 12:20:44 -07:00
Christian Decker
c2a698069e pay: Add an error code to the payments
This allows us to directly returnan error code based on where we
decided to abort, rather than attemtping to infer it from the parts.

Changelog-Added: pay: The pay plugin now returns better error codes
2024-08-08 12:20:44 -07:00
Alex Myers
48258ecb31 reckless: correct logging levels
Some output was hidden under normal operation which should
not have been.
2024-08-08 11:33:39 +09:30
Alex Myers
fe58c731ed reckless: escape strings in log 2024-08-08 11:33:39 +09:30
Alex Myers
9a7481b532 reckless: handle failure to find entrypoint cleanly 2024-08-08 11:33:39 +09:30
Alex Myers
dff7b50040 reckless: handle other --json cases without crashing 2024-08-08 11:33:39 +09:30
Alex Myers
efd67b36f0 reckless: handle unresolvable situations in a --json friendly way 2024-08-08 11:33:39 +09:30
Alex Myers
4aef72648c reckless: accept json array arguments as input
Changelog-Added: Reckless: accepts json array input for command targets
2024-08-08 11:33:39 +09:30
Alex Myers
1ac6e25ffd reckless: don't polute stdout with python install
status if --json was requested.
2024-08-08 11:33:39 +09:30
Alex Myers
bb47bc1d4a reckless: all command functions return objects to enable json out
This more easily allows list output for commands accepting list
input, i.e., installing 3 plugins produces 3 outputs.
2024-08-08 11:33:39 +09:30
Alex Myers
a2e458047f reckless: add json output option
Also redirect config creation prompts to stderr in order to not interfere
with json output on stdout.

Changelog-Added: reckless provides json output with option flag -j/--json
2024-08-08 11:33:39 +09:30
Alex Myers
75d8d8b91f reckless: add logger class
This will allow redirection of json output in the following commits.
2024-08-08 11:33:39 +09:30
Alex Myers
40c24065f7 reckless: make options flags position independent
Changelog-Changed: Reckless option flags are now position independent.
2024-08-08 11:33:39 +09:30
Alex Myers
0a6c58133d reckless: add version information to reckless 2024-08-08 11:33:39 +09:30
Alex Myers
9cbaafb525 reckless: add installer for rust plugins
This follows the same structure that enables python virtual environments:
  reckless/
    <plugin_name>/
      <symlink to compiled bin>
      source/
        <clone of original source plugin dir>/

Changelog-Added: Reckless: added the ability to install rust plugins.
2024-08-08 11:33:39 +09:30
Alex Myers
ed2c0ae18f reckless: place source code in source/plugin_name/
rather than just source/.  This is required for cargo install, so let's just
use this paradigm globally.
2024-08-08 11:33:39 +09:30
Alex Myers
c1d46d6ef9 reckless: add type hints for InstInfo 2024-08-08 11:33:39 +09:30
Alex Myers
7387c9cb1f reckless: remove mimetype
The python mimetype package wasn't useful enough in indentifying
filetypes anyhow.
2024-08-08 11:33:39 +09:30
Rusty Russell
a1fdeee76b Makefile: clean up install path handling.
We had some weird code to try to do relative paths.  Instead, use absolute
ones and keep life simple.  Also rename "daemon_dir" to the clearer
"subdaemon_dir" as that's what it's used for.

We now need special magic to do "installcheck", which is a bit awkward,
but at least it's contained.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-08-07 18:32:56 +02:00
Rusty Russell
f8b259d5e9 askrene: add "auto.localchans" layer.
This populates information on both topology (i.e. unannounced channels) and capacity for the local node using `listpeerchannels`.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-08-07 20:35:30 +09:30
Rusty Russell
b8b8a40e9e askrene: split json_getroutes into two parts.
This will allow us to call an RPC function in the middle.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-08-07 20:35:30 +09:30
Rusty Russell
61ccf18521 devtools/gossmap-compress: allow setting the nodeid explicitly for generated nodes.
This lets us make gossip which contains "real" nodes.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-08-07 20:35:30 +09:30
Rusty Russell
296b3ce20c plugin/askrene: add "auto.sourcefree" layer.
This marks all channels around the source node as free (no delay, no fee).  This is normally what we want, if we are calculating a path for ourselves.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-08-07 20:35:30 +09:30
Rusty Russell
de19524b6d pytest: simple getroutes tests.
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-08-07 20:35:30 +09:30
Rusty Russell
45814bf8ac plugins/askrene: attach getroutes call to MCF code.
Now getroutes actually does something!

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-08-07 20:35:30 +09:30
Rusty Russell
79ceb59d7a plugins/askrene: remove local contexts.
In general, we should be using tmpctx unless there's a specific reason not to.
It's clear, and simplifies the code somewhat.

If tmpctx is not cleaned often enough, we can look at a per-MCF context, but this
seems like premature optimization.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-08-07 20:35:30 +09:30
Rusty Russell
b1817b6c52 askrene: include the mcf and flow routines.
This make the code use askrene's "struct route_query".

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-08-07 20:35:30 +09:30
Rusty Russell
be054dcb3f askrene: make the flow.[ch] files compile.
This adapts them to their new locations, and copies a few more routines.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-08-07 20:35:30 +09:30
Rusty Russell
1db5cf6dea askrene: simply fail if a flow amount exceeds 64 bits.
Rather than handling failure, simply report and exit the plugin.
Simplifies error handling.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-08-07 20:35:30 +09:30
Rusty Russell
7bf399cac5 askrene: remove code which tries to handle tal failures.
tal does not fail: the default handler (which we use) aborts.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-08-07 20:35:30 +09:30
Rusty Russell
37793b0ac2 askrene/flow: don't omit initial hop in flow_spend.
That will be done in the caller, not here.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-08-07 20:35:30 +09:30
Rusty Russell
e4b84f1ffb askrene: copy flow and dijkstra from renepay.
Still don't actually try compiling them.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-08-07 20:35:30 +09:30
Rusty Russell
d109fcb568 askrene: simplify minflow()
We let the caller choose mu, and iterate if necessary: it can also
check its limits for fees, etc.  Rationalize it to 0-100 inclusive for
human consumption.

This means we don't loop internally, and in fact there's only one
failure mode: we cannot find enough capacity.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-08-07 20:35:30 +09:30
Rusty Russell
5999467dce askrene: copy mcf.[ch] from renepay with minimal modifications.
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-08-07 20:35:30 +09:30
Rusty Russell
22a32e6e09 pytest: test file for askrene.
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-08-07 20:35:30 +09:30
Rusty Russell
990bbdde27 askrene: fast lookup for capacities.
We don't know anything about most channels, so we create an array of
fp16_t containing them.  We zero out ones where we do know something,
and use the previous code as the slow path.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-08-07 20:35:30 +09:30
Rusty Russell
eb335ad763 askrene: always set a dummy constraint when we add a local channel.
This means we never have to look up a local channel when asked the capacity.

We mark these dummy constraints with an MAX timestamp.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-08-07 20:35:30 +09:30
Rusty Russell
37bdaff8e2 askrene: flesh out getroutes() a little.
We apply all the gossmods for the layers they specified, and create a
naive routine to give the capacity of a channel given those layers.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-08-07 20:35:30 +09:30
Rusty Russell
c17c240f79 askrene: reservation implementation.
They tell us what paths they're using, so we can adjust capacity estimates
accordingly.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>


Header from folded patch 'reserve-fixup.patch':

fixup! askrene: reservation implementation.
2024-08-07 20:35:30 +09:30
Rusty Russell
d7f983a5b5 askrene: add layers infrastructure.
These are the repositories of all information.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>


Header from folded patch 'layers-fixup.patch':

fixup! askrene: add layers infrastructure.
2024-08-07 20:35:30 +09:30
Rusty Russell
ad209182ba askrene: skeleton which does JSON API.
All the infrastructure and interfaces, but it doesn't do anything yet.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-08-07 20:35:30 +09:30
Rusty Russell
9b19eada30 common: promote useful routines from renepay.
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-08-07 20:35:30 +09:30
Rusty Russell
a29d135bee bitcoin: add short_channel_id_dir_eq.
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-08-07 20:35:30 +09:30
Rusty Russell
9935e28358 common: new parameter parsing routines.
param_u16 (for delay).

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-08-07 20:35:30 +09:30
Rusty Russell
11bfbf5deb libplugin: add data pointer for plugin convenience.
This avoids globals (and means memleak traverses the variables!): we
only change over the test plugin though, to avoid unnecessary churn.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-08-07 20:35:30 +09:30
Rusty Russell
e11bab8bbb gossmap: don't process channel_announcement until amount is present.
This simplifies the callers significantly: all channel_announcements now
have an amount, so gossmap_chan_get_capacity() only fails on a local
modification.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-08-07 20:35:30 +09:30
Rusty Russell
4d593463fa doc: document askrene.
It's experimental, so API may change, but it definitely does need explanation!

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-08-07 20:35:30 +09:30
Rusty Russell
8dbc1c5f2e offers: fix crash when receiving response to offer without offer_issuer_id
Now we actually check the other fields too, as per BOLT!

Reported-by: https://github.com/hMsats
Fixes: #7513
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-08-06 19:09:27 -07:00
Rusty Russell
28b93e1b5f pytest: make GenChannel arguments explicit.
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-08-07 11:18:55 +09:30
Rusty Russell
e3f06b2602 devtools/gossmap-compress: print out node ids.
This helps code using generate_gossip_store() too, since it can map its identifiers
to the nodeids which were used.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-08-07 11:18:55 +09:30
Rusty Russell
53faab0838 pytest: add routine to generate gossmap by topology.
We marshal it into the "compressed" format and get the decompresser to
build the actual gossmap.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-08-07 11:18:55 +09:30
Rusty Russell
99e8e9246e devtools/gossmap-compress: use transparent zlib compression if available.
Before:
```
-rw-rw-r-- 1 rusty rusty 1643258 Jul 26 09:51 compressed
```

After:
```
-rw-rw-r-- 1 rusty rusty 508332 Jul 26 09:49 compressed
```

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-08-07 11:18:55 +09:30
Rusty Russell
c93b4aafb2 devtools/gossmap-compress: decompress code.
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-08-07 11:18:55 +09:30
Rusty Russell
cf936d296e devtools: add gossmap-compress to give minimal representation of gossmap topology.
Simple format, which doesn't include node information, just the channels.

Example:

```
$ ls -l gossip-store-2024-06-26
-rw------- 1 rusty rusty 98815543 Jul 26 09:47 gossip-store-2024-06-26
$ ./devtools/gossmap-compress -v compress gossip-store-2024-06-26 compressed
18693 nodes
61437 channels
46148 disabled channels (32620 no update)
9690 unique capacities
85 unique htlc_min
6867 unique htlc_max
807 unique basefee
2521 unique propfee
94 unique delay
$ ls -l compressed
-rw-rw-r-- 1 rusty rusty 1643258 Jul 26 09:51 compressed
```

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-08-07 11:18:55 +09:30
daywalker90
0a73f918c1 macos: fix ci and autoclean
Changelog-None
2024-08-07 10:57:26 +09:30
ShahanaFarooqui
a82f1feb3a pyln-client: Deprecate category, description and long description from method
Category, description and long description from `json_command` and `plugin_command` have been removed in favour of getting them from json schema.  Reference PR: Add categories in RPC documentation #7485

Deprecating them in pyln-client as well. They will remove completely in future releases.

Changelog-Deprecated: pyln-client: category, description and long descriptions for RPC commands are deprecated now.
2024-08-07 10:19:55 +09:30
Rusty Russell
bb400238b1 gossipd: always ask first peer for all the gossip.
This is a hack, but we've had nodes missing gossip.  LDK does this,
so until we get a better workaround, use this one.

Changelog-Changed: Protocol: we now always ask the first peer for all its gossip.
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-08-07 10:15:03 +09:30
Rusty Russell
855d7366c7 CI: don't fall over if cannot connect to upload server.
```
>           warnings.warn(f"Error reporting testrun: {e}: {e.read()}")
E           AttributeError: 'URLError' object has no attribute 'read'
```

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-08-06 02:00:35 -05:00
Rusty Russell
f77d4d7097 offers: fix flake in fetchinvoice.
In CI, this would sometimes fail: we would timeout waiting for the
fetchinvoice reply.  Never happened locally, so was annoying to debug.

What happened was simple: we called injectonionmessage then when it
returned, put the "sent" object in the linked list so we could recognize
any reply onion messages.

However, we were getting that reply before the plugin processed the response
to injectonionmessage.  This is possible because there are two fds for
plugins: one for it to receive notifications and hooks (like onion messages)
and one for normal RPC usage (like commands to inject onion messages).

The fix is simple: put in the list *before* calling JSON RPC.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-08-05 16:35:15 +02:00
Rusty Russell
2e06d814e5 lightningd: fix false positive in leak detection.
We ask each channeld to report its leaks, and keep a refcount of how
many are outstanding.  When the channeld replies, or dies, we decrement
the count in a destructor.

But if the last channeld we're waiting for dies, we can call the
destructor in an unexpected place, and thus run leak detection when
we were partway through some operation, which gives a false positive.
Here's a backtrace showing it:

```
0x5f93405897e3 send_backtrace
	common/daemon.c:33
0x5f93405381cf finish_report
	lightningd/memdump.c:139
0x5f93405382a0 leak_detect_req_done
	lightningd/memdump.c:172
0x5f9340705c41 notify
	ccan/ccan/tal/tal.c:243
0x5f9340705ca5 del_tree
	ccan/ccan/tal/tal.c:437
0x5f9340705ce8 del_tree
	ccan/ccan/tal/tal.c:447
0x5f93407061f3 tal_free
	ccan/ccan/tal/tal.c:532
0x5f9340563f5a subd_release_channel
	lightningd/subd.c:924
0x5f934050fb91 channel_set_owner
	lightningd/channel.c:31
0x5f9340511b84 channel_err
	lightningd/channel.c:1081
0x5f93405121a3 channel_fail_transient
	lightningd/channel.c:1095
0x5f934054e547 peer_channels_cleanup
	lightningd/peer_control.c:187
0x5f9340550411 peer_connected
	lightningd/peer_control.c:1689
0x5f9340525101 connectd_msg
	lightningd/connect_control.c:629
```

Instead, do the lightningd detection up-front, where it's in a
clean environment.

Reported-by: Shahana Farooqui
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-08-04 11:47:54 +02:00
Rusty Russell
0b4b4c5e03 lightningd: don't create a second peer on stub recover if one already exists.
This was confusing to debug, but if the peer already exists we must not
create a second one.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-08-04 10:48:36 +09:30
Rusty Russell
bf549130d6 global: update BOLT12 quotes.
This is a final sweep to match the current BOLT12 text:

	1563d13999d342680140c693de0b9d65aa522372 ("More bolt12 test vectors.")

Only two code changes, to change the order of checks to match the bolt,
and to give a warning on decode if a path is empty.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-08-01 12:31:48 +09:30
Rusty Russell
f2a7b19281 plugins/offers: handle invreq_paths in invoice_requests, set them if necessary.
Changelog-EXPERIMENTAL: offers: `invoicerequest` will set a blinded path if we're an unannounced node.
Changelog-EXPERIMENTAL: offers: `sendinvoice` will use a blinded path in an invoice_request, if specified.
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-08-01 12:31:48 +09:30
Rusty Russell
71270ae795 lightningd: make the caller set invreq_metadata and invreq_payer_id for createinvoicerequest.
It's an internal undocumented interface, which makes this change less painful.

We *do* check that the invreq_metadata maps to the given invreq_payer_id, which would
is required for us to sign it.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-08-01 12:31:48 +09:30
Rusty Russell
74ef03d361 lightningd: use tweak on node_id of different key, for createinvoicerequest.
It's an internal difference, so doesn't actually break compatibility
(it would if we tried to prove we owned an old invoicerequest, but we
don't have infrastructure for that anyway).

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-08-01 12:31:48 +09:30
Rusty Russell
fa33a2fece lightningd: make plugins set metadata for invoice requests.
They can do it now: before it would have been awkward to look up previous
payments to match it up for recurring offers (which need to use the same
key, hence the same invreq_metadata).

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-08-01 12:31:48 +09:30
Rusty Russell
401d85fce0 lightningd: make invreq metdata deterministic, not random for recurring invoices.
This is going to allow us to move it out from lightingd into plugin,
easily.  It's legal because the combination of offer id and label must
be unique (with recurrence, we use the same metadata anyay, since they
want to correlate with prior payments anyway).

We already broke recurrence in this PR, so we don't need another note to say
we're changing the key derivation.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-08-01 12:31:48 +09:30
Rusty Russell
98f07e92c2 common: fix up some minor typos in BOLT quotes.
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-08-01 12:31:48 +09:30
Rusty Russell
e8a38f111d hsmd: create an hsm variant to sign a bolt12 invoice using a tweak on our key.
The current interface, if given a tweak, uses a *different secret key*
and tweaks it.  This was an early experiment: we will switch to using
a secret tweak for invoice_requests like we do for invoice path ids.

To make sure there's no funny business, *hsmd* hashes to form the
tweak (i.e. no zero tweaks!).

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-08-01 12:31:48 +09:30
Rusty Russell
09401e34b6 common/bolt12_id: generate alias tweak.
For now we only use a fake id for requesting invoices (as a payer_key), but we
will eventually use this generically, and we want plugins to be able to map them
too, so use the same scheme as path_id: a generated secret using the makesecret
API.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-08-01 12:31:48 +09:30
Rusty Russell
ee47b9370f common/bolt12_id: new common routine for creating path secrets.
invoice_path_id is actually a generic path_id thing, so rename it.

We're going to use the same scheme for path secrets and the tweak to
node_id when we create a fake pubkey for invoice_requests, so a new
header is appropriate.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-08-01 12:31:48 +09:30
Rusty Russell
363e1ee44c common: update test to encode new test vectors now we handle them correctly.
1. Missing offer_description iff offer_amount also missing.
2. Missing offer_issuer_id iff offer_paths is present.
3. Short channel id on introduction point.
4. Experimental range.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-08-01 12:31:48 +09:30
Rusty Russell
d740795139 common/bolt12: allow missing offer_issuer_id.
The latest spec allows this to be omitted iff there is a blinded path
and it would be made up anyway.

In that case, the key they will use to sign the invoice will be the final
blinded key in the path we use.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-08-01 12:31:48 +09:30
Rusty Russell
2ecf5e6bd5 BOLT12: reject zero-length blinded paths.
This is a good idea, but also specifically called out in the latest BOLT spec.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-08-01 12:31:48 +09:30
Rusty Russell
18fc1b82b0 wire: add new field invreq_paths from spec.
This is the blinded path for offerless invoice_requests.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-08-01 12:31:48 +09:30
Rusty Russell
0f0a0cf153 doc: mark schema offer_node_id and warning_missing_offer_node_id deprecated.
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-08-01 12:31:48 +09:30
Rusty Russell
925e90ee8b wire: rename "offer_node_id" to "offer_issuer_id" to match latest BOLT.
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-08-01 12:31:48 +09:30
Rusty Russell
f42e9b3fe6 wire: renumber experimental recurring offer fields.
The `invreq_recurrence_counter` clashes with the coming addition of
invreq_paths, so we might as well move them all to the new experimental
ranges.

Changelog-EXPERIMENTAL: Recurring offers had incompatible changes, won't work against older versions.
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-08-01 12:31:48 +09:30
Rusty Russell
ef2905895b offers: fix invoice return comparison.
This mistake was revealed when we start using experimental range for recurrence
(next commit).

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-08-01 12:31:48 +09:30
Pavol Rusnak
5c494488e7 pyln-proto: update cryptography to v42
Changelog-None
2024-07-31 16:34:55 +02:00
michael1011
46c3920585 grpc-plugin: Run cargo fmt for minor style fixes 2024-07-31 08:53:12 +02:00
michael1011
9b1f331748 Revert "ci: Pin rustc to version 1.78 due to a type inference regression"
This reverts commit 76ad48cd1b.
2024-07-31 08:53:12 +02:00
michael1011
27df5aa03b grpc-plugin: Update rcgen
The version of rcgen that was used before does not compile with
the latest stable Rust release v1.80
2024-07-31 08:53:12 +02:00
ShahanaFarooqui
2ff3e55f08 plugin: Removing category, description and long_description from plugin_command struct
Changelog-None.
2024-07-31 14:42:58 +09:30
ShahanaFarooqui
b485a026f7 rpc: Removing description from json_command struct 2024-07-31 14:42:58 +09:30
ShahanaFarooqui
89c182e2be rpc: Removing category and verbose from json_command struct 2024-07-31 14:42:58 +09:30
ShahanaFarooqui
58e3ea574c docs: Adding readonly category for all get & list commands except listdatastore 2024-07-31 14:42:58 +09:30
Christian Decker
10acbffcf9 onchaind: Remove key derivation involving the signer
The signer may not be present at this time. If we want to keep the
check to protect against bit flips we should move it into `onchaind`
where it doesn't matter as much that the signer may be slow to
respond.
2024-07-29 17:08:33 +02:00
Christian Decker
d496126af8 tests: Adjust tests for the lack of unilateral attempt now 2024-07-29 17:08:33 +02:00
Christian Decker
6c972cdb32 close: Do not publish unilateral when witnessing a close onchain
Changelog-Changed: close: We no longer attempt to publish a unilateral close that'd fail anyway when we witness a close onchain.
2024-07-29 17:08:33 +02:00
Christian Decker
76ad48cd1b ci: Pin rustc to version 1.78 due to a type inference regression
Changelog-None
2024-07-26 15:22:04 +02:00
Rusty Russell
15fb37f6d1 common: fix endless loop in gossmap iteration.
If we need to iterate forward to find a timestamp (only happens if we have gossip older than
2 hours), we didn't exit the loop, as it didn't actually move the offset.

Fixes: https://github.com/ElementsProject/lightning/issues/7462
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-07-25 12:30:42 -07:00
Rusty Russell
88024fa8d6 common/bolt12, offers plugin: handle experimental ranges in bolt12 correctly.
The latest draft allows these experimental ranges, which involves more
changes than I expected.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
Changelog-EXPERIMENTAL: offers: handle experimental ranges in offers/invoice_requests/invoices.
2024-07-23 09:54:47 +09:30
Rusty Russell
6d6716c9ec devtools/bolt12-cli: fix decoding of unknown fields.
We had known vs unknown backwards ("it's OK to be odd!")

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-07-23 09:54:47 +09:30
Rusty Russell
c342f204b2 common/wire: update, don't replace fields array in TLV structures.
Regnerating them entirely loses unknown fields.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-07-23 09:54:47 +09:30
Rusty Russell
ea4025b1ed plugins/offers: fix JSON output of decode when there are unknown fields.
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-07-23 09:54:47 +09:30
Rusty Russell
1e2c6a5837 common: maintain unknown fields when unmarshalling/marshalling TLVs
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
Changelog-EXPERIMENTAL: offers: maintain unknown fields offers/invoice_requests correctly.
2024-07-23 09:54:47 +09:30
Rusty Russell
7735eb6767 doc: allow "offer_description" to be missing in decode.
This is now allowed to be omitted.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-07-23 09:54:47 +09:30
Rusty Russell
90b06bbd13 msggen: fix up previous generated "deprecated": false.
Between this and the last fix, we can now deprecate things in future.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-07-23 09:54:47 +09:30
Rusty Russell
0a1aa972d8 msggen: fix deprecated from "False" to "None".
Turns out we set this to False instead of None, so new field get "deprecated": False.
When we actually deprecate one, we get the following error:

	ValueError: Field Decode.offer_node_id changed `deprecated` annotation: v24.08 vs False

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-07-23 09:54:47 +09:30
Rusty Russell
21a83a8f79 wire: remove unused obsolete file.
This is from back when we removed EXPERIMENTAL builds.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-07-23 09:54:47 +09:30
Rusty Russell
c68204a32a lightningd: store our id as a struct pubkey as well as struct node_id.
We convert it in various places, so do that only once.  Also, the name
"id" is a little curt.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-07-23 09:54:47 +09:30
Rusty Russell
af90fdc0bb common/utils: macros to help get copy/compare across different types right.
Things are often equivalent but different types:
1. u8 arrays in libwally.
2. sha256
3. Secrets derived via sha256
4. txids

Rather than open-coding a BUILD_ASSERT & memcpy, create a macro to do it.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-07-23 09:54:47 +09:30
Jon Griffiths
bc5c528910 wally: update libwally to 1.3.0
Changelog-Changed: Update libwally to 1.3.0

Signed-off-by: Jon Griffiths <jon_p_griffiths@yahoo.com>
2024-07-22 10:19:35 +09:30
Joseph Goulden
89ede8a208 plugins/sql: allow datetime functions
Changelog-Changed: Plugins:  now allows date and time sqlite functions.
2024-07-19 15:40:06 +09:30
ShahanaFarooqui
6bfa303a4a doc: Tiny corrections in documentation
Changelog-None.
2024-07-17 22:35:37 -07:00
Rusty Russell
3c04b6f8d3 lightningd: remove expermential "sendonionmessage" function.
It was only ever expermental, so I don't feel bad about just removing it.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
Changelog-Removed: JSON-RPC: `sendonionmessage` (was experimental only, use `injectonionmessage`)
2024-07-18 10:53:55 +09:30
Rusty Russell
91cd68920c pay: handle case where we are head of blinded path, and next hop is scid.
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-07-18 10:53:55 +09:30
Rusty Russell
f00f832b96 plugins/pay: pay to invoices where first hop is a short_channel_id_dir.
Changelog-Added: Protocol: pay can now pay to bolt12 invoices if entry to blinded hop is specified as a short_channel_id (rather than node id).
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-07-18 10:53:55 +09:30
Rusty Russell
b29b96aae8 common: hoist scidd->pubkey conversion function into gossmap.
We will want to use it in the pay plugin too.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-07-18 10:53:55 +09:30
Rusty Russell
272d313e05 offers: add self-fetchinvoices for offers, and self-pay for the resulting invoice.
Changelog-Added: offers: we can now self-fetch and self-pay BOLT12 offers and invoices.
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-07-18 10:53:55 +09:30
Rusty Russell
9faffeb2e6 plugins/offers: create blinded path if necessary.
This also lets us test offers and invoices work if we are the start of
the blinded path.

Changelog-Added: offers: automatically add a blinded path from a peer if we have no public channels, so unannounced nodes can have offers too.
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-07-18 10:53:55 +09:30
Rusty Russell
55982fe549 offers: generalize "best peer" logic into core.
We use this for invoices published by unannounced nodes: want
something very similar for offers, so generalize and expose it.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-07-18 10:53:55 +09:30
Rusty Russell
ca1b469c1a plugin/pay: Handle paying to blinded path starting with us.
Ideally, we would be able to submit a payment exactly as an incoming
HTLC would, but our forwarding and decoding logic is currently very
much tied to the HTLC.  It would be wonderful to detach that and
have an "injectonion" interface which was unwrapped like any other
(see "injectonionmessage") which would handle self-pay without any
special paths.

Since I'm not prepared to rewrite that all now, instead we use an
interface to decrypt the first hop if it's us, and use the remainder
of the blinded path.

Changelog-Fixed: plugins: pay can now pay a bolt12 invoice even if we, ourselves, are the head of the blinded path within it.
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-07-18 10:53:55 +09:30
Rusty Russell
de0d371d20 lightningd: new internal JSONRPC "decryptencrypteddata"
I'm not sure about interface yet, so don't document.  It's ugly.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-07-18 10:53:55 +09:30
Rusty Russell
e8b959ac77 plugins/offers: allow reversal of a single-element path for reply.
Don't refuse, this will happen if we are the head of the blinded path,
for example.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-07-18 10:53:55 +09:30
Rusty Russell
47c1ca8d85 plugins/pay: separate route destination and pay destination.
For bolt12, we have blinded paths so we route to the head of the blinded
path, which may not be the same as the final payment destination.

This matters mainly for detecting self-pay.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-07-18 10:53:55 +09:30
Rusty Russell
73e5d9a78a pytest: fix flake in test_fetchinvoice
On my local machine it can run into ratelimiting, because I miscounted the fetchinvoice
calls.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-07-18 10:53:55 +09:30
Rusty Russell
6bf41f4807 unittests: use current version of BOLTS when reading specs.
We check out the master bolts branch, and that recently changed test vectors
causing our CI to change.  We should test them against our current BOLTVERSION,
which is in .tmp.lightningrfc/

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-07-17 10:57:11 +02:00
Rusty Russell
6a98de5830 pytest: add simple test for offers with paths.
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-07-17 10:57:11 +02:00
Rusty Russell
dacf81672e plugins/offers: improve reply path logic.
We generate a reply path by simply reversing the outgoing path:

	A->B->C gives reply path B->A
	A->B gives reply path A

But if we are not a public node, we can't use ourselves as the first
entry of the reply path: this happens if we directly connect to the
head of a blinded path (as we now support).

In this case, give the entire path as a blinded path.  We could do
this all the time, but there are some cases where nodes don't like
sending replies where the node itself is the head of the blinded
path (like CLN v24.05 or before!).

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-07-17 10:57:11 +02:00
Rusty Russell
ea5ea14df4 establish_onion_path: allow establishment via any connected peer.
We only need a connection with a peer, not an actual channel.  So
add all peers to the local gossmap.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-07-17 10:57:11 +02:00
Rusty Russell
0d4b9ad6ce offers: check they use the blinded path if one is specified.
Now we can specify a blinded path in an offer, we have to check they
used it (or didn't use it, if we didn't have one!).

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-07-17 10:57:11 +02:00
Rusty Russell
27578d5c1d plugins/offers: add dev-paths option for specifying offers blinded paths.
This will let us test, at least, as we implement fetching invoices from
them.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-07-17 10:57:11 +02:00
Rusty Russell
92eb84d45f fetchinvoice: don't call establish_onion_path ourselves, now send_message does it.
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-07-17 10:57:11 +02:00
Rusty Russell
1a4256842c fetchinvoice: handle blinded paths in offers.
We iterate through the blinded paths until we can use one, and because we use
the modern code, we properly join paths if we need to route more than one hop
to reach the start of the blinded path.

Changelog-EXPERIMENTAL: fixed: fetchinvoice tries all blinded paths until one is usable, and handles case where we have to route more than one hop to reach the entry point.
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-07-17 10:57:11 +02:00
Rusty Russell
ef641e81c6 fetchinvoice: don't stash path in sent object, hand directly.
Simplification.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-07-17 10:57:11 +02:00
Rusty Russell
a6cfdea71b fetchinvoice: use common/onion_message routines.
This is significantly simpler, too.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-07-17 10:57:11 +02:00
Rusty Russell
386f7ab64c plugins/offers: don't establish_onion_path at start of processing invoice_request
send_onion_reply() does that for us now, so we don't need to do it up-front.

Simplifies the code quite a bit.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-07-17 10:57:11 +02:00
Rusty Russell
a43705194d plugins/offers: make send_onion_reply() handle making transient connections.
And make it use inject_onionmessage.  This means we have to be more careful
in createinvoice_done where we had a payload field allocated off tmpctx.

The new code correctly handles the case where we find a path (not just
a peer!) to the start of a blinded path, and need to join the paths.

It worked before if we had to connect directly, just not in the case
where we actually found a usable route of more than 1 hop.

Changelog-EXPERIMENTAL: fixed: onionmessage replies now work even if we need to route to the start of the blinded reply path.
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-07-17 10:57:11 +02:00
Rusty Russell
fa9574da6e plugins/offers: use common/onion_message routines in invoice_request handling.
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-07-17 10:57:11 +02:00
Rusty Russell
8c81d6a0b9 plugin/offers: add inject_onionmessage helper.
This will obsolete the existing calls to RPC "sendonionmessage", but
we transition by introducing it separately.  It's designed to work with
the common/onion_message routines and "injectonionmessage".

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-07-17 10:57:11 +02:00
Rusty Russell
eee7344bf2 common/onion_message: new unified, documented routines for making onion messages.
This is complicated, and I needed to write it down.  All the current routines
are spread through the code, and I wanted it all in one place.

This implementation also support *joining* two paths together, which we
previously didn't.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-07-17 10:57:11 +02:00
Rusty Russell
d664d52342 plugins/offers: neaten fetchinvoice integration.
We already parse some fields, so hand them directly rather than
having fetchinvoice behave as if it's a raw hook.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-07-17 10:57:11 +02:00
Rusty Russell
a782ea75b5 plugins: move fetchinvoice functionality into offers plugin.
This means only a single gossmap, and they already share the fetchinvoice-noconnect option
and autoconnect code.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
Changelog-Changed: Plugins: the `fetchinvoice` plugin has been combined into the `offers` plugin.
2024-07-17 10:57:11 +02:00
ShahanaFarooqui
1e1d072b65 ci: Adding new step to run basic tests on minimum supported BTC version
As suggested by @rustyrussell, Adding another step for testing minimum supported Bitcoin version with clang test suite.

Changelog-None.
2024-07-16 16:10:51 -05:00
ShahanaFarooqui
57814766bc doc: Update README for BTC min version 2024-07-16 16:10:51 -05:00
Dusty Daemon
21bc89f189 splice: Add funding outnum
Fixes #7005

Changelog-Changed: Added outnum of new funding output to splice_signed RPC command
2024-07-15 13:31:01 -05:00
ShahanaFarooqui
d77301c338 git: Ignore .doc_version
With recent updates in PR #7444, the file is created but should not be uploaded to git.

Changelog-None.
2024-07-15 13:00:48 -05:00
Rusty Russell
e910418373 Makefile: check formatting of notification schemas too.
We had an extra space, which should have been caught!

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-07-12 17:30:14 -07:00
Rusty Russell
418887b24a doc: fix up added versions for notification schemas.
The *schemas* were added in v24.05, but the actual fields are much older.  Unfortunately,
fixing this required a manual edit of the .msggen.json file, as msggen won't let the
added version change (for good reason).

Versions when these notifications were originally added:
connect: v0.6.3
channel_opened: v0.7.2.1:
channel_state_changed: v0.9.1
channel_open_failed: v0.9.3
block_added: v22.11
custommsg: v24.02

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-07-12 17:30:14 -07:00
Vincenzo Palazzo
05f5976a9c bolt12: partial support for minimal offer
Making sure that we are able to fetch the invoice
from an offer without description

E           pyln.client.lightning.RpcError: RPC call failed: method:
offer, payload: {'amount': '2msat'}, error: {'code': -32602, 'message':
'bolt12: Offer does not contain a description: invalid token
\'"lno1qgsqvgnwgcg35z6ee2h3yczraddm72xrfua9uve2rlrm9deu7xyfzrcgqyppvggz953rvg9rtxj8lalh43z8epwydjfrmffn3y3p5qz5cywpu09rr4vs"\''}

Link: https://github.com/ElementsProject/lightning/issues/7405
Link: https://github.com/ElementsProject/lightning/issues/7404
Signed-off-by: Vincenzo Palazzo <vincenzopalazzodev@gmail.com>
2024-07-11 14:51:56 +09:30
Rusty Russell
029034a71b config: onion messages are now always enabled.
Changelog-Added: Protocol: onion messages are now supported by default.
Changelog-Deprecated: Config: the --experimental-onion-messages option is ignored (on by default).
2024-07-10 13:34:00 +02:00
Rusty Russell
5d42600076 connectd: ratelimit onion messages
However fast we can handle them, it's antisocial to allow others to
make us spam the rest of the network.

Changelog-Protocol: onion messages: we limit incoming to 4 per second, allowing a little burst.
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-07-10 13:34:00 +02:00
Rusty Russell
621bfe370e connectd: forward onion messages by scid as well as node_id.
This is now permitted in the offers PR, so we should support it.  But
we can't just look up in the gossmap, since the "short_channel_id"
could be an alias.  So we get lightningd to tell us all scid->peer
mappings, and look up in that.

Changelog-Added: Protocol: onion messages can now be forwarded by short_channel_id.
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-07-10 13:34:00 +02:00
Rusty Russell
19af516dcb lightningd: tell connectd about all scids.
When we set them (i.e. at lockin), when we fire up channeld (for
aliases, which we create at channel init, but aren't really useful
until we have finished channel opening), and at startup.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-07-10 13:34:00 +02:00
Rusty Russell
f122c0beb4 connectd: include map of scid->peer node id.
This will let us fwd onion messages via scid, even if they're aliases.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-07-10 13:34:00 +02:00
Rusty Russell
b5f921ce0a lightningd: add routine to directly inject an onion message.
Unlike "sendonionmessage" which instructs us to send to a peer, this
process it locally (presumably, it contains the next hop).  This is
useful because it allows us to process an onion message which starts
with us (a legal case for a blinded path supplied by someone else!).
It also opens the door to bolt12 self-pay.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-07-10 13:34:00 +02:00
Rusty Russell
ba82592196 common/onion_message_parse: return string, not bool.
Allows for caller to log, but more importantly, when we add a command to
inject onion messages, allows for us to capture the error.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-07-10 13:34:00 +02:00
Tommy Volk
a3c15e8a4a chore: add ShortChannelId::to_u64 2024-07-10 11:49:19 +02:00
Rusty Russell
242ecbc906 Makefile: only run cppcheck on non-generated files.
For some reason CI now hits a race where it tries to analyze a still-being-generated file:

```
tools/headerversions.c:52:30: error: syntax error [syntaxError]
 new = tal_fmt(NULL, template,
                             ^
make: *** [Makefile:552: check-cppcheck] Error 123
```

Restrict it to real source files instead.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-07-10 12:21:19 +09:30
Rusty Russell
47584bd504 connectd: tie gossip query responses into ratelimiting code.
A bit tricky, since we get more than one message at a time.  However,
this just means we go over quota for a bit, and will get caught when
those are sent (we do this for a single message already, so it's not
that much worse).

Note: this not only limits sending, but it limits the actuall query
processing, which is nice.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-07-10 12:21:19 +09:30
Rusty Russell
4a78d17748 connectd: do response to gossip queries, don't hand them to gossipd.
This basically means moving the code from gossipd to connectd to handle
these queries.

This will get connectd have finer control over ratelimiting them.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-07-10 12:21:19 +09:30
Rusty Russell
531845971c gossipd: drop zlib support.
This was removed from the spec on Apr 25, 2022.  We stopped ever sending them
in 0.12.0 (2022-08-23).  Now we remove receive support.

Changelog-Protocol: Removed support for zlib-compressed short-channel-ids in query responses.
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-07-10 12:21:19 +09:30
Rusty Russell
d60977f37f connectd: use gossmap streaming interface.
This is more efficient in a few ways:
1. It's trivial to get to the end of the gossip_store, we don't have
   to iterate.
2. It tends to be mmaped so we don't have to call pread().

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-07-10 12:21:19 +09:30
Rusty Russell
ba2bb5531d gossmap: add linear streaming interface.
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-07-10 12:21:19 +09:30
Rusty Russell
ae5ad486ea gossipd: delete empty gossipd_peerd_wire.csv
gossipd no longer connects directly to per-peer daemons, so remove old file.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-07-10 12:21:19 +09:30
Rusty Russell
401533667d connectd: throttle streaming gossip for peers.
We currently stream gossip as fast as we can, even if they start at
timestamp 0.  Instead, use a simple token bucket filter and only let
them have 1MB per second (500 bytes per second for testing).

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
Changelog-Protocol: connectd: we now throttle outgoing gossip at 1MB/second per peer.
2024-07-10 12:21:19 +09:30
Rusty Russell
7f71e6353a doc: fix schema for listconfigs.
We never call `listconfigs` in our tests with `experimental-offers` enabled,
so we didn't notice that the schema is wrong: it does not expect the
"plugin" field in 'fetchinvoice-noconnect'.

The next patch folds the fetchinvoice plugin into the offers plugin,
which is enabled even if `experimental-offers` isn't (for `decode`),
so we notice it.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-07-09 15:09:29 +02:00
Rusty Russell
991f6dcb0f config: actually deprecate --experimental-anchors.
Document and enforce the --experimental-anchors deprecation, which was somehow missed in v24.02

Changelog-Deprecated: Config: the --experimental-anchors option is ignored (on by default since v24.02).
2024-07-09 15:09:29 +02:00
Rusty Russell
0c7ce27a39 plugins/offers: establish_onion_path can have a simple boolean arg for connect_disable.
It's always the same string, so simplify the interface.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-07-09 15:09:29 +02:00
Rusty Russell
34052f9960 bitcoin: hoist scid hash into common code.
A second user is coming.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-07-09 15:09:29 +02:00
Rusty Russell
fa0926148d common: make struct sphinx_hop more generic.
Only sphinx internally uses the hmac field: it's actually a general descriptor
of onion contents, which we can use elsewhere.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-07-09 15:09:29 +02:00
Rusty Russell
5e585d061f connectd: log incoming onion message IO properly.
I noticed we were missing this.  Move logging up a level so it's easier to
spot the omission.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-07-09 15:09:29 +02:00
Rusty Russell
d7fa88b686 lightningd: clarify bolt12 "payment secret" logic.
We don't use the payment_secret in bolt12, but in onion_decode() we
do put the path_secret (if of correct length) into payment_secret.  Not
realizing this confused me, so document that, and make sure we insist
on it being present for bolt12.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-07-09 15:09:29 +02:00
Rusty Russell
4647f3c2a3 common: don't pass (unused) has_realm parameter to process_onionpacket.
This was when we handled pre-TLV onions where the first byte was 0.  We haven't
done that for a while: you can tell, because process_onionpacket doesn't use
the parameter at all!

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-07-09 15:09:29 +02:00
Rusty Russell
f64d48e716 plugins/pay: fix crash if we try to self-pay a bolt12 invoice.
It doesn't work but at least now it doesn't crash!

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-07-09 15:09:29 +02:00
Rusty Russell
ec2b626630 plugins/pay: don't crash if getroute is empty.
This can't happen because we go the self-pay path in this case, but
once we fix that for bolt12, this can be reached.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-07-09 15:09:29 +02:00
Rusty Russell
162ebe2a72 global: we always offer OPT_ROUTE_BLINDING, don't need to test.
We did since v23.05.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-07-09 15:09:29 +02:00
Rusty Russell
01cd605cb1 connectd: fix missing peer close.
We were getting the following message in test_feerate_stress:

```
2024-07-08T02:15:45.5663941Z lightningd-2 2024-07-08T02:13:45.696Z **BROKEN** 0266e4598d1d3c415f572a8488830b60f7e744ed9235eb0b1ba93283b315c03518-connectd: Peer did not close, forcing close
```

I can reproduce it locally if I run the test enough, and finally found
the issue by printing the status of the fd when we time it out (using
routines from connectd.c).

The peer fd alternates between reading and writing.  When we go to
discard it, we wake the write queue, so write_to_peer() get called.
It won't shutdown the socket if there are still subds attached, and
will wait again for a read.

The last subd exit has to also wake the write queue if we're draining,
so it can do the io_sock_shutdown.  Otherwise, we hit the timeout,
causing the message above.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-07-09 18:03:44 +09:30
Rusty Russell
578b297d46 ccan: update to get fdpass fix.
Theoretical only, but we could leak an fd if we closed a conn before
the fd was sent.  This doesn't happen in our current codebase because
we only hand fds to connectd, which only closes at shutdown.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-07-09 18:03:44 +09:30
Rusty Russell
6f8754a72b common/msg_queue: make sure to close any pending fds on destruction.
We only hand fds to connectd for now, so this doesn't happen (we don't
destroy that queue except on shutdown).  But it's still a potential issue.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-07-09 18:03:44 +09:30
Rusty Russell
5a5fee92b3 connectd: don't report socket fds twice.
The initial commit had this code twice, for some reason!

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-07-09 18:03:44 +09:30
jackstar12
feaac0eb4f msggen: add missing-grpc command 2024-07-06 09:05:08 +09:30
ShahanaFarooqui
4b69c57d75 plugins: Remove requirements.txt for python plugins
Removing requirements.txt from clnrest and wss-proxy plugins due to their ever changing dependencies. We will only be dependent on pyproject.toml for more stable results.

Reference: https://github.com/ElementsProject/lightning/pull/7416#issuecomment-2181492069

Changelog-None.
2024-07-03 12:20:05 -07:00
niftynei
c6ac45d743 fundchannel: remove crash on race condition
If the peer sends you their signatures before we return from the *first*
openchannel_update then the state would still be in
MULTIFUNDCHANNEL_STARTED (not UPDATED) and we'd incorrectly switch the
state to MULTIFUNDCHANNEL_SIGNED, which would plunge us headfirst into
`check_sigs_ready`.

However the `mfc->txid` hadn't been set yet, so we'd crash when trying
to confirm that we've got sigs for the correct txid. Oops.

To fix this, we simply invert the check such that the *only* state that
will move into SIGNED is SECURED
2024-07-03 09:11:52 +09:30
Rusty Russell
eb1c04ef14 wire: optimize sending packets now we can return EAGAIN.
Interestingly, this patch and the last take my total test time on my
build machine down by about 10%.  From 403.93s (0:06:43) to 366.64s (0:06:06)
though there were some unrelated errors.

Changelog-Changed: connectd: I/O optimizations to significantly speed up larger nodes.
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-07-02 15:16:55 -07:00
Rusty Russell
341b62eea3 ccan: update for more efficient ccan/io.
A fairly simple change: ccan/io will now call the underlying I/O
routines repeatedly until they indicate they are unfinished, *or* fail
with EAGAIN.  This should make a significant difference to large
nodes, which currently spend far too much time calling poll() to
discover a single fd is still writable (mainly, for streaming gossip).

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
Changelog-Changed: connectd: now should use far less CPU on large nodes.
2024-07-02 15:16:55 -07:00
Rusty Russell
7ef8645aad Makefile: don't make every file depend on version headers.
common/version.o depends on common/version_gen.h explicitly already,
and header_versions_gen.h is only used by lightningd, so we can make
that dependency explicit.

This means when version changes (i.e. different git commit) we only
relink, not recompile.

Before:
```
real	0m6.578s
user	0m14.705s
sys	0m13.621s
```

After:
```
real	0m2.098s
user	0m6.763s
sys	0m4.844s
```

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-07-02 10:00:55 +02:00
Rusty Russell
d922c89b4d doc: don't include exact version in manpages.
This slows compilation somewhat when we make small changes (e.g. making the tree dirty).
Instead, simply mark them as "pre-XXX" or "XXX".

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-07-02 10:00:55 +02:00
Rusty Russell
d6ae456309 doc: speed "noop" compilation times by not force-building markdown and man pages every time.
Their dependencies seem correct, so we shouldn't have to build them every time.

Before:
```shell
$ time make -s
real	0m5.183s
user	0m5.134s
sys	0m11.715s
```

After:

```shell
$ time make -s
real	0m0.784s
user	0m0.775s
sys	0m1.159s
```

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-07-02 10:00:55 +02:00
Erik De Smedt
62e82c20d7 Fix: Add notifications.rs to $(CHECK_GEN_ALL) target
The file `cln-rpc/src/notifications.rs` is generated by `msggen`.

The `Makefile` has tooling to update the file when needed
- `make check-gen-updated` should error if file isn't properly updated
- `make gen` updates the file

This comit fixes both behaviors mentioned above.
2024-07-02 11:42:14 +09:30
ShahanaFarooqui
7783658489 ci: Unify bitcoin versions for whole project
- Updated all Bitcoin version 27.1
- Updated all Elements versions 23.2.1

Changelog-Changed: Updated Bitcoin to v27.1 and Elements to v23.2.1
2024-07-02 11:41:36 +09:30
ShahanaFarooqui
545d67eaf6 doc: Updated warning box for wss-proxy
Bug Fix: The wss-proxy plugin throws error `plugin-wss-proxy: Killing plugin: disabled itself at init: Error in parsing options: 'NoneType' object is not subscriptable` if CLN is not listening on websocket.

Reference: https://github.com/ElementsProject/lightning/issues/7386#issuecomment-2175766309

Changelog-None.
2024-06-28 11:03:07 +09:30
ShahanaFarooqui
39626b9f8f clnrest: Fixes ssl_version deprecated warning
Reference Issue #6931: Fixes `Warning: option `ssl_version` is deprecated and it is ignored. Use ssl_context instead.`

Changelog-None.
2024-06-28 10:54:44 +09:30
ShahanaFarooqui
9f599365f9 clnrest: Updated requirements.txt (without coincurve)
As suggested by @cdecker, I compared `poetry show --tree` results from before/after `cd plugins/clnrest/ && poetry export --output requirements.txt && pip install -r requirements.txt` to check for any significant difference. There is no difference in the tree.

But poetry export removed coincurve & other dependencies from clnrest's requirements.txt.

Changelog-None.
2024-06-28 10:46:14 +09:30
daywalker90
c251686c6c pyln-proto: update coincurve to v20
Changelog-None
2024-06-28 10:46:14 +09:30
ShahanaFarooqui
7baa1e93ca docs: Fixes typo in library name flask-restx
clnrest installation instruction on the markdown tries to install `flask_restx` not `flask-restx`.

Reference: clnrest plugin complains of flask_restx missing (#7383)

Changelog-None.
2024-06-26 21:31:49 -07:00
ShahanaFarooqui
cd07ce83f7 docs: Moved python plugins after CLN instructions
Changelog-None.
2024-06-26 21:31:49 -07:00
Epic Curious
6c338d6173 fix(deps): add pytest dependency for make check 2024-06-26 21:31:49 -07:00
Epic Curious
41c766882b docs: chore: bump lightning tag in installation.md 2024-06-26 21:31:49 -07:00
Epic Curious
5c43d44800 fix(deps): add python3-pip to clnrest dependencies 2024-06-26 21:31:49 -07:00
Epic Curious
1cb749ecbb fix(deps): add libsecp256k1-dev to clnrest plugin instructions 2024-06-26 21:31:49 -07:00
Epic Curious
02262586ec fix(deps): add libffi-dev build dependency
Fix the fatal error  `ffi.h: No such file or directory` during pip3 install requirements.txt
2024-06-26 21:31:49 -07:00
ShahanaFarooqui
51e46339a7 docs: notifications schema update
Changelog-None.
2024-06-26 21:06:16 -07:00
ShahanaFarooqui
72079cc920 script: Adding Delete action for readme docs
Documents which are deleted from lightning schema were still listed on readme server.

This script was adding or updating the list but delete action was missing.

Changelog-None.
2024-06-25 12:34:07 -07:00
Rusty Russell
c30502779e CI: set elements and bitcoind versions in one place.
We have them spread everywhere: unify them, and make setup.sh use install-bitcoind.sh

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-06-25 09:36:00 +09:30
Rusty Russell
cb4dd7489c lightningd: check command should return as much detail as possible.
If they're explicitly calling "check", don't obfuscate the result!

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-06-25 08:47:50 +09:30
Rusty Russell
9fd29d35dd common: move now-enlarged command_fail_badparam into its own source file.
It's getting a bit awkward to inline now: it's non-trivial.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-06-25 08:47:50 +09:30
Rusty Russell
f33c5188ef common: don't mention the contents of invalid parameters when in non-dev mode.
Shahana decided this was the optimal UX path, though I insisted that we still
report the actual problem directly when in dev mode, as a compromise.

Suggested-by: https://github.com/Amperstrand
Changelog-Changed: JSON-RPC: Do not return the contents of invalid parameters in error messages, refer to logs (use 'check' to get full error messages)
Fixes: https://github.com/ElementsProject/lightning/issues/7338
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-06-25 08:47:50 +09:30
Rusty Russell
e0e38c2cd5 common: new function command_log to log something about a specific command.
Needs implementations for lightningd and libplugin, since they both use this
infrastructure.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-06-25 08:47:50 +09:30
Rusty Russell
3531414d18 lightningd: rename command_log() to command_logger()
It doesn't actually log, just gets the `struct logger`, so this name is better.

We're also going to implement command_log() as an actual logging
function in next commit.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-06-25 08:47:50 +09:30
Rusty Russell
8288603bab pytest: fix flake in test_emergencyrecover
```
2024-06-24T05:09:32.5233603Z         assert l1.rpc.listfunds()["channels"][0]["state"] == "ONCHAIN"
2024-06-24T05:09:32.5234187Z >       assert l2.rpc.listfunds()["channels"][0]["state"] == "ONCHAIN"
2024-06-24T05:09:32.5234917Z E       AssertionError: assert 'FUNDING_SPEND_SEEN' == 'ONCHAIN'
2024-06-24T05:09:32.5235464Z E         - ONCHAIN
2024-06-24T05:09:32.5235773Z E         + FUNDING_SPEND_SEEN
2024-06-24T05:09:32.5236096Z 
2024-06-24T05:09:32.5236242Z tests/test_misc.py:2907: AssertionError
```

It's possible that l2 hasn't seen the onchain tx yet.  What we really want to do is
wait for it, then test that l1 really can spend the output it has recovered.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-06-24 21:12:43 +09:30
Rusty Russell
f642e4e551 pytest: fix test_feerate_stress race
```
2024-06-24T05:14:14.9939033Z >       l1.rpc.call('dev-feerate', [l2.info['id'], rate - 5])
2024-06-24T05:14:14.9939354Z 
2024-06-24T05:14:14.9939466Z tests/test_connection.py:3439: 
...
2024-06-24T05:14:14.9967617Z >           raise RpcError(method, payload, resp['error'])
2024-06-24T05:14:14.9968833Z E           pyln.client.lightning.RpcError: RPC call failed: method: dev-feerate, payload: ['022d223620a359a47ff7f7ac447c85c46c923da53389221a0054c11c1e3ca31d59', 2290], error: {'code': -1, 'message': 'Peer bad state'}
```

The disconnect can actually take a while: wait for both sides to
believe they're reconnected.  Also wait a little to make sure the
feerate change doesn't create a bad signature.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-06-24 21:12:43 +09:30
Rusty Russell
bb64fc8ddc pytest: fix flake in test_feerate_stress.
If randomly l1done or l2done are zero, we will create invalid hex:

```
with pytest.raises(RpcError, match='WIRE_INCORRECT_OR_UNKNOWN_PAYMENT_DETAILS|WIRE_TEMPORARY_CHANNEL_FAILURE'):
>           l2.rpc.waitsendpay("{:064x}".format(l2done - 1), timeout=TIMEOUT)

tests/test_connection.py:3438: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
contrib/pyln-client/pyln/client/lightning.py:1361: in waitsendpay
    return self.call("waitsendpay", payload)
contrib/pyln-testing/pyln/testing/utils.py:715: in call
    schemas[0].validate(testpayload)
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = Validator(schema={'pairedWith': [['partid', 'groupid']], 'properties': {'groupid': {'description': ['Grouping key...pa... {'description': ['A timeout in... the payment.'], 'type': 'u32'}}, 'required': ['payment_hash']}, format_checker=None)
args = ({'payment_hash': '-000000000000000000000000000000000000000000000000000000000000001', 'timeout': 180},)
kwargs = {}
error = <ValidationError: "'-000000000000000000000000000000000000000000000000000000000000001' is not of type 'hash'">

    def validate(self, *args, **kwargs):
        for error in self.iter_errors(*args, **kwargs):
>           raise error
E           jsonschema.exceptions.ValidationError: '-000000000000000000000000000000000000000000000000000000000000001' is not of type 'hash'
E           
E           Failed validating 'type' in schema['properties']['payment_hash']:
E               {'description': ['The hash of the *payment_preimage*.'], 'type': 'hash'}
E           
E           On instance['payment_hash']:
E               '-000000000000000000000000000000000000000000000000000000000000001'
```

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-06-24 21:12:43 +09:30
Rusty Russell
fd9975c288 reckless: don't use time-based directories.
This always fails on my test machine, which runs many tests in parallel.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-06-24 21:12:43 +09:30
Rusty Russell
b748c1845c pytest: fix flake in test_closing.py::test_penalty_htlc_tx_timeout
lightningd-3 penalizes lightningd-2 but then it can see the preimage for the HTLC which
has already been timed out:

```
2024-06-24T02:41:29.4633900Z lightningd-3 2024-06-24T02:33:54.073Z **BROKEN** 022d223620a359a47ff7f7ac447c85c46c923da53389221a0054c11c1e3ca31d59-onchaind-chan#1: HTLC already resolved by THEIR_HTLC_TIMEOUT_TO_THEM when we found preimage
```

This is fair: the test deliberately takes l3 offline for long enough
that the HTLC can get timed out.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-06-24 21:12:43 +09:30
Rusty Russell
80cde517c9 lightningd: fix race in initialization.
Found by very slow CI: the two io_breaks() can combine into one, so we
block waiting for the second initialization which never happens.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-06-24 17:26:11 +09:30
Rusty Russell
9da66100c1 chaintopology: free outstanding requests so we don't get responses while shutting down.
I've never seen this, but the race looks possible so we should close it.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-06-24 17:26:11 +09:30
Rusty Russell
928b7c83fc lightningd: pass explicit context for bitcoind request functions.
That way if you free the context, you free the call (i.e. the callback
will not be called).

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-06-24 17:26:11 +09:30
Rusty Russell
492ed84dbf lightningd: move checkchain_timer out of bitcoind, remove stopped flag.
checkchain_timer is run by chaintopology, so why have the pointer in
bitcoind?

And since we free the timers, we don't need them to self-disable by
checking the stopped flag.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-06-24 17:26:11 +09:30
Rusty Russell
f2b033d7e1 lightningd: move all chainheight logic into setup_topology.
Handling half in main() and half here was a mess.  And the name
"max_blockheight" was poor: it was the max in the db, or UINT32_MAX,
but then we changed it depending on what height we wanted to start at.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-06-24 17:26:11 +09:30
Rusty Russell
ff15b943fe lightningd: remove unused "min_blockheight" from chain_topology struct.
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-06-24 17:26:11 +09:30
Rusty Russell
f643fb88f5 lightningd: wait for bitcoind at startup if it's fallen behind.
Fixes: https://github.com/ElementsProject/lightning/issues/6924
Changelog-Changed: lightningd: we wait for bitcoind if it has somehow gone backwards (as long as header height is still ok).
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-06-24 17:26:11 +09:30
Rusty Russell
59afbac7cf lightningd: remove first_call param for getchaininfo.
It was a weird arbitrary bool passed through from the caller, which we no longer need.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-06-24 17:26:11 +09:30
Rusty Russell
eb70476fb3 lightningd: split chaintopology init from normal loops.
The current code is confusing: there are polling loops, but we wait for
them to run once. 

Be explicit: make the calls once, then start the loops in begin_topology.

This removes various chain_topology struct members which only exist for
startup.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-06-24 17:26:11 +09:30
Rusty Russell
f318d08e94 lightningd: add arg to bitcoind_estimate_fees callback.
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-06-24 17:26:11 +09:30
Rusty Russell
436bf6c9e1 lightningd: pass height back from getrawblockbyheight.
Several callers stash this, but we have it, so make it explicit:
here's the block you asked for.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-06-24 17:26:11 +09:30
ShahanaFarooqui
b803609247 docs: Removed example usage
Example usage has been either merged with examples or usage keys. This heading was not required separately.

This PR edits & rearranges Examples, Example Notifications and Example Usage data.

Changelog-None.
2024-06-22 17:02:33 +02:00
ShahanaFarooqui
e94b793f05 docs: Example notifications heading
- Added missing Example Notifications Heading
- Renamed `example_json_notifications` to `example_notifications`
- Moved `example_notifications` to the end of the page
2024-06-22 17:02:33 +02:00
ShahanaFarooqui
976c0c90bc docs: Changes examples format
- Changed ALL `doc/schemas/lightning-*.json` file's `json_example` to `examples`
- Change the heading from example to examples
- Bring shell command before the json command
- Move Example to the end of the page
- Remove horizontal line from Example
2024-06-22 17:02:33 +02:00
Christian Decker
1347e86671 wallet: Log to chan->log rather than wallet->log
Suggested-by: Rusty Russell <@rustyrussell>
2024-06-22 14:50:21 +02:00
Christian Decker
001b190c61 feat(main): Print channel status when loading it from DB
I was trying to debug a node with several multiplexed channels, and
was finding it a bit difficult to determine which channel index
matches which result of `listpeerchannels` as well as figuring out
what their status was. This just prints the status in string format
when loading the channel from the DB.

Changelog-Changed: wallet: The channel status is printed when loading it from the DB
2024-06-22 14:50:21 +02:00
Rusty Russell
e21b70cad0 pytest: fix default/description order in zeroconf test plugin.
Noticed as I was debugging.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-06-20 17:20:06 +09:30
Christian Decker
31cf9225f4 pyln: Turn the plugin options into a real Type (uppercase T)
[ Fix not to include 'value' and 'default' (if None) in getmanifest response --RR ]
[ Fix to support [] operator for existing plugins (including our test ones!) --RR ]
2024-06-20 17:20:06 +09:30
Rusty Russell
1eb1db0e24 pyln-client: allow dynamic option setter to throw exceptions
And don't set the value unless it passes.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-06-20 17:20:06 +09:30
Christian Decker
457d25c1ce pyln: Drive-by type fixed 2024-06-20 17:20:06 +09:30
Christian Decker
2737f2e97e pyln: Add and test a callback based setconfig listener
I was looking into using the `threading.Condition` but since we're
already rather heavily using callbacks, this allows us to stay
single-threaded, and not having to completely hook the `setconfig`
function.

Changelog-Added: pyln-client: Added a notification mechanism for config changes
2024-06-20 17:20:06 +09:30
Rusty Russell
572ccac0e5 pyln-client: allow dynamic=True add_option to actually allow updates.
We didn't actually *change* the value you'd see, when we got a setconfig call!

Changelog-Added: pyln-client: implement setconfig hook for plugins so you can see changes in `dynamic` options.
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-06-20 17:20:06 +09:30
Rusty Russell
ead211e5e4 autoclean: call list in easy stages.
listforwards on a large node can easily run out of memory.  Sip, don't
gulp!

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-06-20 16:14:38 +09:30
Rusty Russell
c62e1f432f autoclean: use filter to reduce processing.
We can filter down to only the list* fields we need.  In the case of a
node with 1M forwards, this reduces listforwards time from 5 seconds
to 4 seconds.  It will also reduce memory consumption.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-06-20 16:14:38 +09:30
Rusty Russell
c7ce9c55df libplugin: add plugin_option_dev_dynamic (our first dynamic dev option coming).
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-06-20 16:14:38 +09:30
Rusty Russell
1f9ddd24b2 libplugin: support filtering of outgoing commands.
This is crude, handing a raw JSON string, but it works.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-06-20 16:14:38 +09:30
Rusty Russell
d2465d4498 autoclean: rework logic to clarify subsystems.
There are really three subsystems: invoices, forwards and sendpays,
each of which has two variants we care about (successes and failures).
If we split the code that way, we can extract the core differences in
each of these cases and share most of the logic.

It's a bit awkward to iterate over each "subsystem" in the JSON
parameter sense, so we have some iteration code to do that where we
need to.

The result is going to be much easier to paginate!

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-06-20 16:14:38 +09:30
Rusty Russell
83eed5ce8e autoclean: use a pointer for our global clean_info.
We're about to make this a more complex struct, so introducing a
new_clean_info() function unifies the code paths.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-06-20 16:14:38 +09:30
Rusty Russell
84b6601bb3 autoclean: remove autocleaninvoice command.
Changelog-Removed: JSON-RPC: `autocleaninvoice` command (deprecated v22.11, EOL v24.02)
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-06-20 16:14:38 +09:30
Rusty Russell
b525e26fa5 lightningd: don't load all forwardings into memory at once.
Use modern-style iterators: this can be huge and we will run out of
memory!

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-06-20 16:14:38 +09:30
daywalker90
6ad8cfdffa CI: upgrade CI actions to latest releases
Changelog-None
2024-06-19 21:21:00 -07:00
fanquake
2614dfc104 ci: use Bitcoin Core 27.1
Changelog-None
2024-06-20 11:28:21 +09:30
Niklas Gögge
259015720e fuzz: Add input for from_bech32_charset off-by-one bug 2024-06-20 10:53:50 +09:30
Rusty Russell
1a1696f2f9 lightningd: don't try to "save" incoming channel by closing early if incoming already onchain.
From test_penalty_htlc_tx_timeout[False] flake (with keys replaced by l2 and l5, for clarity)

```
lightningd-3 2024-06-04T04:34:00.942Z UNUSUAL l2-chan#1: Peer permanent failure in CHANNELD_NORMAL: Funding transaction spent
lightningd-3 2024-06-04T04:34:01.570Z UNUSUAL l5-chan#3: Peer permanent failure in CHANNELD_NORMAL: Funding transaction spent
lightningd-3 2024-06-04T04:34:01.655Z UNUSUAL l5-chan#3: Abandoning unresolved onchain HTLC at block 132 (expired at 125) to avoid peer closing incoming HTLC at block 131
lightningd-3 2024-06-04T04:34:02.802Z **BROKEN** l5-chan#3: FUNDS LOSS of 50000000msat: peer took funds onchain before we could time out the HTLC, but we abandoned incoming HTLC to save the incoming channel
```

So, we were already closing l2, no reason to abandon it.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-06-19 23:58:50 +02:00
Rusty Russell
db67df3364 lightningd: log BROKEN if we lost funds, only unusual if we closed abandoned HTLC.
Started seeing these in my logs, and it's the wrong way around!

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-06-19 23:58:50 +02:00
Rusty Russell
0afaf2f3ca msggen: don't spam every time we rebuild.
2923 lines of output?  Even with warnings-only, it's 59 lines, so only
enable that with `make V=1`.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-06-19 12:34:41 +02:00
Rusty Russell
7c3aa9477f pyproject.toml: Update ancient flake8
v4.0 no longer works for me (see below, and widely reported elsewhere).
v5.0 doesn't understand f strings, and creates a flood of complaints.
v6.0 requires python >= 3.8.1, so we need to update that.
v7.0 is the latest, but why push it.

```
make check-python-flake8
Traceback (most recent call last):
  File "/home/rusty/.cache/pypoetry/virtualenvs/cln-meta-project-BgKQHyxC-py3.12/bin/flake8", line 8, in <module>
    sys.exit(main())
             ^^^^^^
  File "/home/rusty/.cache/pypoetry/virtualenvs/cln-meta-project-BgKQHyxC-py3.12/lib/python3.12/site-packages/flake8/main/cli.py", line 22, in main
    app.run(argv)
  File "/home/rusty/.cache/pypoetry/virtualenvs/cln-meta-project-BgKQHyxC-py3.12/lib/python3.12/site-packages/flake8/main/application.py", line 375, in run
    self._run(argv)
  File "/home/rusty/.cache/pypoetry/virtualenvs/cln-meta-project-BgKQHyxC-py3.12/lib/python3.12/site-packages/flake8/main/application.py", line 363, in _run
    self.initialize(argv)
  File "/home/rusty/.cache/pypoetry/virtualenvs/cln-meta-project-BgKQHyxC-py3.12/lib/python3.12/site-packages/flake8/main/application.py", line 343, in initialize
    self.find_plugins(config_finder)
  File "/home/rusty/.cache/pypoetry/virtualenvs/cln-meta-project-BgKQHyxC-py3.12/lib/python3.12/site-packages/flake8/main/application.py", line 157, in find_plugins
    self.check_plugins = plugin_manager.Checkers(local_plugins.extension)
                         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/rusty/.cache/pypoetry/virtualenvs/cln-meta-project-BgKQHyxC-py3.12/lib/python3.12/site-packages/flake8/plugins/manager.py", line 363, in __init__
    self.manager = PluginManager(
                   ^^^^^^^^^^^^^^
  File "/home/rusty/.cache/pypoetry/virtualenvs/cln-meta-project-BgKQHyxC-py3.12/lib/python3.12/site-packages/flake8/plugins/manager.py", line 243, in __init__
    self._load_entrypoint_plugins()
  File "/home/rusty/.cache/pypoetry/virtualenvs/cln-meta-project-BgKQHyxC-py3.12/lib/python3.12/site-packages/flake8/plugins/manager.py", line 261, in _load_entrypoint_plugins
    eps = importlib_metadata.entry_points().get(self.namespace, ())
          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
AttributeError: 'EntryPoints' object has no attribute 'get'
make: *** [Makefile:535: check-python-flake8] Error 1
```

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-06-19 12:34:41 +02:00
ShahanaFarooqui
3d841d5b8a doc: Added Miscellaneous section for Docker users
Added CLN image execution and testing hints for Docker users.

Changelog-None.
2024-06-19 18:41:53 +09:30
ShahanaFarooqui
aba767114c doc: fixed broken link to setting-up-multiarchqemu-user-static
Changelog-None.
2024-06-19 18:41:07 +09:30
ShahanaFarooqui
7e46eb8bc4 docker: Update github actions for Docker releases
This PR is adding github action for auto Docker releases. This will streamline Docker image builds & releases for enhanced efficiency, reliability, and consistency in managing Docker-based deployments.

The build & release event will be triggered:
- On any new tag creation without rc suffix.
- Manually for testing purposes.

Changelog-None.
2024-06-19 18:40:07 +09:30
ShahanaFarooqui
44de5023cb docs: Updated scripts for rpc examples
This update will add lightning-cli examples and make examples heading collapsible.

- The JSON EXAMPLES heading is collapsible now

- Examples in lightning-cli format also

- manpage examples have better formatting

Changelog-None.
2024-06-19 15:56:22 +09:30
ShahanaFarooqui
a4e7079fc1 docs: Removed null values from example request params 2024-06-19 15:56:22 +09:30
ShahanaFarooqui
ec250069b9 docs: Updated req params type from string to object 2024-06-19 15:56:22 +09:30
Rusty Russell
2175cd7db3 onchaind: remove support for rescuing non-static channels when we've lost data.
We could get the current key from the reestablish message even if we'd
lost our db, but there are very few of these channels left: we upgraded to use them
in the 2019-01-09 release.

We will eventually remove support altogether, but this is a nice removal of
some ugly code for something which "never happens".

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-06-19 15:54:24 +09:30
Rusty Russell
002dc60b33 Gossip: BOLT catch, remove initial_routing_sync.
Everyone sends a gossip_timestamp_filter message these days to start gossip.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-06-19 15:54:24 +09:30
Rusty Russell
06cf5ac841 Doc: update bolts to assume gossip_queries under the new meaning.
Everyone understands gossip_queries now, but peers leave it unset to indicate
they have nothing useful to say.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-06-19 15:54:24 +09:30
Rusty Russell
65ef909bd3 Doc: update to BOLT which assumes option_var_onion_optin.
We have assumed this for a long time, so nothing changes.

Confusingly, this BOLT commit also cleaned up one reamining `option_anchors_zero_fee_htlc_tx`.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-06-19 15:54:24 +09:30
Rusty Russell
7f2aedc76f common: BOLT update: option_anchors_zero_fee_htlc_tx is now simply "option_anchors".
This is a difficult transition for us: this string appears in channel
types.  We make the transition now in the understanding that it will
be more difficult in future.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>

Changelog-Deprecated: JSON-RPC: `listpeers` `features` array string "option_anchors_zero_fee_htlc_tx": use "option_anchors" (spec renamed it).
Changelog-Added: JSON-RPC: `listpeers` `features` array string uses "option_anchors" for feature 22/23, following renaming in BOLT 9.
Changelog-Changed: JSON-RPC: `listclosedchannels`, `listpeerchannels`, `openchannel_update`, `openchannel_init`, `fundchannel`, `fundchannel_start` and `multifundchannel`: `channel_type` array `names` now contains "anchors" instead of "anchors_zero_fee_htlc_tx".
Changelog-Changed: lightningd: `--list-features-only` now lists "option_anchors" instead of "option_anchors_zero_fee_htlc_tx".
2024-06-19 15:54:24 +09:30
Rusty Russell
7d3d763b96 channeld: BOLT update, no longer allow creation of old (experimental-only!) non-zero-fee anchor channels.
These were removed from the spec.

We still support existing ones, though we were the only implementation
which ever did, and only in experimental mode, so we should be able to
upgrade them and avoid a forced close, with a bit of engineering...

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-06-19 15:54:24 +09:30
Rusty Russell
b6d7ee1f11 common: No longer support new channels without option_static_remotekey.
We still support *existing* channels.  Just not new ones (before they could,
in theory, explicitly ask for one).

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-06-19 15:54:24 +09:30
Rusty Russell
e0b4a579b1 common: update BOLTs to bring LaTeX formatting into onion spec.
Soo.... pretty....

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-06-19 15:54:24 +09:30
Rusty Russell
f1d78ff35a common/onion_decode: update to latest BOLT spec, reject encrypted_recipient_data with both scid and node.
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-06-19 15:54:24 +09:30
Rusty Russell
4a36edf7c1 tools/check-bolt: rewrite to give more accurate diagnostics when we're out of sync.
Just use substrings not regexes, since we have more complex characters now LaTeX
is entering the spec!

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-06-19 15:54:24 +09:30
Rusty Russell
1de569d38d devtools/gossipwith: use timestamp filter message not obsolete INIT_ROUTING_SYNC.
This means we do have to set the network correctly though,
and also we can get query messages from lightningd which we have to filter.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-06-19 15:54:24 +09:30
Erik De Smedt
daf9d27777 poetry: Use non-package mode
Since `poetry=1.8.0` there is a non-package mode. This can be used to
create `pyproject.toml` files that are only used to track dependencies.

Performing `poetry install` in the project-root with a recent version of `poetry`
is currently generating a warning which will become an error in the
future.

Setting `package-mode=false` makes this error go away.

A side-effect is that the `name`, `version` and `description` in the
`pyproject.toml`-file will be ignored. Keeping the parameters in the
`pyproject.toml` file ensures it will still work for developers who are
using `poetry<1.8.0`.
2024-06-18 16:55:01 -07:00
ShahanaFarooqui
fd855755ef script: Adjusting the script with ubuntu:noble updates 2024-06-18 16:53:32 -07:00
ShahanaFarooqui
8c852dca02 script: Adding cl-repro script for easier builder image building
This script is useful for contributors to create reproducible binaries, signing and verifying releases.

Changelog-None.
2024-06-18 16:53:32 -07:00
Jose Storopoli
9ceac8e49d doc: fix markdown in configuration node options 2024-06-18 16:46:11 -07:00
ShahanaFarooqui
35101c072a commando: update removal version for rpcs
We documented them as deprecated in v23.08 but unintentionally didn't deprecate them in the code. Thus we are starting their actual deprecation cycle from v24.08 release.

Updating removal version for commands `commando-rune`, `commando-listrunes`, and `commando-blacklist`

Changelog-None.
2024-06-18 14:06:06 +09:30
ShahanaFarooqui
f5f2ab17a0 doc: Fixed decode first_scid and first_scid_dir descriptions 2024-06-18 14:06:06 +09:30
Rusty Russell
a43fc91f8f configure: don't sanitize function call types.
We do this with typesafe_cb and it's so useful I'm not going to remove it.  But clang 18 complains:

```
ccan/ccan/tal/tal.c:246:6: runtime error: call to function destroy_conn_close_fd through pointer to incorrect function type 'void (*)(void *)'
/home/rusty/devel/cvs/lightning/ccan/ccan/io/poll.c:251: note: destroy_conn_close_fd defined here
```

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-06-18 13:21:12 +09:30
Rusty Russell
d1d9d7ee6f offers: remove deprecated @ prefix.
Somehow, this documentation got lost during the Great Rewrite, so
restore that too.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
Changelog-EXPERIMENTAL: JSON-RPC: `offer` removed `@` prefix support from `recurrence_base` (use `recurrence_start_any_period` set to `false`)
2024-06-14 11:30:26 +09:30
Rusty Russell
fc2f1f42c6 bcli: remove deprecated estimatefees responses.
Changelog-Removed: Plugins: `estimatefees` returning feerates by name (e.g. "opening"); deprecated in v23.05.
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-06-14 11:30:26 +09:30
Rusty Russell
ba69007f7b Makefile: next version is 24.08.
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-06-14 11:30:26 +09:30
Vincenzo Palazzo
f2551091ca offer: make the blockheight nullable
However, it is possible to avoid this kind of crash, because
our assert is "wrong" because blockheight can be 0 and the
assert can fail.

In addition, the `rpc_scan` already checks for nullability, so the
assert is redundant

2024-06-07T14:14:29.278Z INFO    lightningd: v24.05-modded
2024-06-07T14:14:37.158Z INFO    lightningd: v24.05-modded
2024-06-07T14:14:29.329Z INFO    lightningd: Creating configuration directory /root/.lightning/signet
2024-06-07T14:14:37.589Z INFO    plugin-bcli: bitcoin-cli initialized and connected to bitcoind.
2024-06-07T14:14:29.715Z INFO    lightningd: Creating database
2024-06-07T14:14:37.591Z UNUSUAL lightningd: Waiting for initial block download (this can take a while!)
2024-06-07T14:14:29.752Z UNUSUAL hsmd: HSM: created new hsm_secret file
2024-06-07T14:14:37.603Z INFO    plugin-reckless-wrapper.py: initializing reckless-wrapper.py.
2024-06-07T14:14:29.798Z INFO    plugin-bcli: bitcoin-cli initialized and connected to bitcoind.
2024-06-07T14:14:29.802Z UNUSUAL lightningd: Waiting for initial block download (this can take a while!)
offers: plugins/offers.c:1235: init: Assertion `blockheight' failed.
2024-06-07T14:14:29.814Z INFO    plugin-reckless-wrapper.py: initializing reckless-wrapper.py.
offers: FATAL SIGNAL 6 (version v24.05-modded)
0x57ab55a56485 send_backtrace
2024-06-07T14:14:29.818Z INFO    plugin-chanbackup: Creating Emergency Recovery
   common/daemon.c:33
offers: plugins/offers.c:1235: init: Assertion `blockheight' failed.
offers: FATAL SIGNAL 6 (version v24.05-modded)
0x57ab55a5650d crashdump
   common/daemon.c:75
0x59f3ed3ba485 send_backtrace
0x7dd20b02213f ???
   common/daemon.c:33
   ???:0
0x59f3ed3ba50d crashdump
0x7dd20ae59ce1 ???
   common/daemon.c:75
   ???:0
0x7dd20ae43536 ???
0x764fa583813f ???
   ???:0
0x7dd20ae4340e ???
   ???:0
0x7dd20ae52661 ???
   ???:0
   ???:0
0x57ab55a3effe init
   plugins/offers.c:1235
0x764fa566fce1 ???
0x57ab55a4763f handle_init
   ???:0
   plugins/libplugin.c:1376
0x57ab55a478ee ld_command_handle
0x764fa5659536 ???
   plugins/libplugin.c:1797
0x57ab55a47ec0 ld_read_json_one
   plugins/libplugin.c:1979
   ???:0
0x57ab55a47f49 ld_read_json
0x764fa565940e ???
   plugins/libplugin.c:1999
   ???:0
0x57ab55b934cc next_plan
0x764fa5668661 ???
   ccan/ccan/io/io.c:60
   ???:0
0x57ab55b93953 do_plan
0x59f3ed3a2ffe init
   ccan/ccan/io/io.c:408
   plugins/offers.c:1235
0x57ab55b939ec io_ready
   ccan/ccan/io/io.c:418
0x59f3ed3ab63f handle_init
0x57ab55b95302 io_loop
   plugins/libplugin.c:1376
   ccan/ccan/io/poll.c:455
0x59f3ed3ab8ee ld_command_handle
0x57ab55a486dc plugin_main
   plugins/libplugin.c:1797
   plugins/libplugin.c:2209
0x59f3ed3abec0 ld_read_json_one
0x57ab55a3f36d main
   plugins/libplugin.c:1979
   plugins/offers.c:1285
0x59f3ed3abf49 ld_read_json
0x7dd20ae44d09 ???
   plugins/libplugin.c:1999
   ???:0
0x59f3ed4f74cc next_plan
0x57ab55a3c799 ???
   ccan/ccan/io/io.c:60
0x59f3ed4f7953 do_plan
   ???:0
   ccan/ccan/io/io.c:408
0xffffffffffffffff ???
0x59f3ed4f79ec io_ready
   ccan/ccan/io/io.c:418
   ???:0
offers: FATAL SIGNAL 11 (version v24.05-modded)
0x59f3ed4f9302 io_loop
   ccan/ccan/io/poll.c:455
0x57ab55a56485 send_backtrace
0x59f3ed3ac6dc plugin_main
   common/daemon.c:33
   plugins/libplugin.c:2209
0x57ab55a5650d crashdump
0x59f3ed3a336d main
   plugins/offers.c:1285
   common/daemon.c:75
0x7dd20b02213f ???
0x764fa565ad09 ???
   ???:0
   ???:0
0x59f3ed3a0799 ???
0x0 ???
   ???:0
   ???:0
2024-06-07T14:14:37.734Z INFO    plugin-offers: Killing plugin: exited before replying to init
0xffffffffffffffff ???
   ???:0
2024-06-07T14:14:37.734Z **BROKEN** plugin-offers: Plugin marked as important, shutting down lightningd!
offers: FATAL SIGNAL 11 (version v24.05-modded)
0x59f3ed3ba485 send_backtrace
   common/daemon.c:33
0x59f3ed3ba50d crashdump
   common/daemon.c:75
0x764fa583813f ???
   ???:0
0x0 ???
   ???:0
2024-06-07T14:14:29.823Z INFO    plugin-bookkeeper: Creating database
2024-06-07T14:14:29.883Z INFO    plugin-offers: Killing plugin: exited before replying to init
2024-06-07T14:14:29.883Z **BROKEN** plugin-offers: Plugin marked as important, shutting down lightningd!

Fixes: 9d75fbe237
Reported-by: @farscapian
Link: https://github.com/ElementsProject/lightning/issues/7378
Signed-off-by: Vincenzo Palazzo <vincenzopalazzodev@gmail.com>
2024-06-14 10:39:02 +09:30
ShahanaFarooqui
a064b1a4a8 docker: poetry install before make
Issue: Docker images for v24.05 were built on clean lightning directory and the published image should be running on v24.05 but it is running as v24.05-modded.

Root cause: Dockerfile builder was running different versions of grpcio-tools and protobuf. It resulted in auto generated update of contrib/pyln-grpc-proto/pyln/grpc/node_pb2.py and contrib/pyln-grpc-proto/pyln/grpc/primitive_pb2.py files.

Solution: Run `poetry install` before make in the dockerfile's builder stage to ensure that the grpcio-tools and protobuf versions are the same.

References:
https://github.com/ElementsProject/lightning/issues/7370#issuecomment-2152952820
https://github.com/ElementsProject/lightning/pull/7376#issuecomment-2161102381

Changelog-None.
2024-06-13 11:43:37 +09:30
ShahanaFarooqui
c9c1df6710 script: Added caching option for docker publish and shellcheck fixes
Changelog-None.
2024-06-13 11:43:37 +09:30
Rusty Russell
11586abf79 CHANGELOG.md: make more consistent.
1. Plugin things should all be prefixed by `Plugins:` then the name of the plugin altered.
2. New config options should always be named in CHANGELOG.md!
3. Unify groups of changes into a single line, in this case, GRPC.
4. Command, plugin and option names are in backticks.
5. Offers changes are still under EXPERIMENTAL.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-06-04 20:23:24 -05:00
Alex Myers
36367ca0d9 meta: update changelog for v24.05
Changelog-None
2024-06-04 20:23:24 -05:00
Alex Myers
b17bc9cc69 meta: bump rust versions for 24.05 release 2024-06-04 20:23:24 -05:00
Rusty Russell
107fc8b9fb gossipd: fix crash when processing pending node_announcements.
When we process pending channel updates, it can cause the node_announcement
to be moved.  Then, we process a new node_announcement and go to delete
the old one, but it's already moved!

Do the obvious thing, and refresh gossmap if necessary each time around
the loop.

```
2024-05-17T02:56:12.701Z **BROKEN** gossipd: gossip_store: get delete entry offset 554921761/585584347 (version v24.02.1-151-g6e2ab02-modded)
2024-05-17T02:56:12.701Z **BROKEN** gossipd: backtrace: common/daemon.c:38 (send_backtrace) 0x55b4c962518b
2024-05-17T02:56:12.701Z **BROKEN** gossipd: backtrace: common/status.c:221 (status_failed) 0x55b4c962e83e
2024-05-17T02:56:12.701Z **BROKEN** gossipd: backtrace: gossipd/gossip_store.c:466 (gossip_store_get_with_hdr) 0x55b4c961b6e3
2024-05-17T02:56:12.701Z **BROKEN** gossipd: backtrace: gossipd/gossip_store.c:491 (check_msg_type) 0x55b4c961b75d
2024-05-17T02:56:12.701Z **BROKEN** gossipd: backtrace: gossipd/gossip_store.c:509 (gossip_store_set_flag) 0x55b4c961b8e0
2024-05-17T02:56:12.701Z **BROKEN** gossipd: backtrace: gossipd/gossip_store.c:561 (gossip_store_del) 0x55b4c961bb26
2024-05-17T02:56:12.701Z **BROKEN** gossipd: backtrace: gossipd/gossmap_manage.c:913 (process_node_announcement) 0x55b4c961c472
2024-05-17T02:56:12.701Z **BROKEN** gossipd: backtrace: gossipd/gossmap_manage.c:1111 (reprocess_queued_msgs) 0x55b4c961d6a6
2024-05-17T02:56:12.701Z **BROKEN** gossipd: backtrace: gossipd/gossmap_manage.c:670 (gossmap_manage_handle_get_txout_reply) 0x55b4c961d840
2024-05-17T02:56:12.702Z **BROKEN** gossipd: backtrace: gossipd/gossipd.c:585 (recv_req) 0x55b4c9619e6a
2024-05-17T02:56:12.702Z **BROKEN** gossipd: backtrace: common/daemon_conn.c:35 (handle_read) 0x55b4c9625436
2024-05-17T02:56:12.702Z **BROKEN** gossipd: backtrace: ccan/ccan/io/io.c:59 (next_plan) 0x55b4c96b8506
2024-05-17T02:56:12.702Z **BROKEN** gossipd: backtrace: ccan/ccan/io/io.c:407 (do_plan) 0x55b4c96b898d
2024-05-17T02:56:12.702Z **BROKEN** gossipd: backtrace: ccan/ccan/io/io.c:417 (io_ready) 0x55b4c96b8a26
2024-05-17T02:56:12.702Z **BROKEN** gossipd: backtrace: ccan/ccan/io/poll.c:453 (io_loop) 0x55b4c96ba315
2024-05-17T02:56:12.702Z **BROKEN** gossipd: backtrace: gossipd/gossipd.c:683 (main) 0x55b4c961a84c
2024-05-17T02:56:12.702Z **BROKEN** gossipd: backtrace: ../csu/libc-start.c:308 (__libc_start_main) 0x7f3931a3dd09
2024-05-17T02:56:12.702Z **BROKEN** gossipd: backtrace: (null):0 ((null)) 0x55b4c9616d39
2024-05-17T02:56:12.702Z **BROKEN** gossipd: backtrace: (null):0 ((null)) 0xffffffffffffffff
2024-05-17T02:56:12.702Z **BROKEN** gossipd: STATUS_FAIL_INTERNAL_ERROR: gossip_store: get delete entry offset 554921761/585584347
```

Reported-by: Vincenzo Palazzo
Fixes: https://github.com/ElementsProject/lightning/issues/7320
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-06-04 08:09:54 -05:00
ShahanaFarooqui
3dc6e6d29e script: Add reproducible build script for Ubuntu v24.04
This PR will help in publishing CLN reproducible binaries for Ubuntu v24.04 (noble).

Please note that I adjusted Dockerfiles for focal and jammy also to keep the base image creation script same for all three images. The step update was required because `noble` only runs with ubuntu:noble setup.

Changelog-None.
2024-06-03 14:23:36 -05:00
ShahanaFarooqui
fbd454bd31 docs: Update chat links
- Added badges for BoL2, Telegram and Discord.
- rearranged chat links.
2024-05-31 09:43:18 +09:30
Alex Myers
f109bc27e1 meta: update changelog for 24.05rc2 2024-05-29 20:16:44 -05:00
Rusty Russell
818cf06139 common: translate legacy onion payloads.
We do this by literally creating the modern-style TLV, and pretending we found it in the onion.

This isolates us from messing with any callers, who don't even know.

Co-programmed-with: Alex Myers <alex@endothermic.dev>
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
Fixes: https://github.com/ElementsProject/lightning/issues/7347
Changelog-Fixed: Protocol: forward legacy non-TLV onions which we removed in 22.11 and spec itself in Feb 2022.  Still sent by LND nodes who haven't seen our node_announcement.
2024-05-29 12:40:01 -05:00
Rusty Russell
a4732177bb pytest: test for forwarding legacy onion.
This fails, because l2 can't decode the onion:

```
lightningd-2 2024-05-28T21:43:35.137Z DEBUG   0266e4598d1d3c415f572a8488830b60f7e744ed9235eb0b1ba93283b315c03518-chan#1: Rejecting their htlc 0 since onion is unprocessable WIRE_INVALID_ONION_HMAC ss=4202c24ea44d9029a2ea3abb24cded51da93164f8bb5cddce9cc824af9945435
```

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-05-29 12:40:01 -05:00
Rusty Russell
288c47483f lightningd: pay dev_legacy_hop arg to make second-last onion a v0.
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-05-29 12:40:01 -05:00
Rusty Russell
f26b140acb common: re-add legacy v0 hop generation to Sphinx for testing.
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-05-29 12:40:01 -05:00
Rusty Russell
1d4783a756 lightningd: send CHANNEL_REESTABLISH ourselves on closed channels.
We used to fire up channeld to send this, but:
1. That's silly, we have all the information to make it ourselves.
2. We didn't do it if there was an error on the channel, which as of 24.02
   there always is!
3. When it did work, running channeld *stops* onchaind, indefinitely slowing recovery.

Fixes: https://github.com/Blockstream/greenlight/issues/433
Changelog-Fixed: Protocol: we once again send CHANNEL_REESTABLISH responses on closing channels.
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-05-29 12:39:20 -05:00
Rusty Russell
f9e7d5653a pytest: test that we get REESTABLISH msg reply on closed channels.
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-05-29 12:39:20 -05:00
Aditya Sharma
4789eb9fa0 chanbackup: typo fix. 2024-05-29 10:34:58 -05:00
ShahanaFarooqui
43f4e12cde docs: Type change for request amount too
For multifund and openchannel_init schemas, request_amt type is also `sat`.
2024-05-28 09:49:17 -05:00
daywalker90
0eb65e4bb5 schemas: use sat and sat_or_all again where appropiate
Changelog-None
2024-05-28 09:49:17 -05:00
Rusty Russell
964c0732cf pytest: remove xfail in test (accidental commit?)
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-05-28 09:42:36 -05:00
ShahanaFarooqui
7f5282aa65 docker: Add missing git dependency for Fedora Dockerfile
Fedora image building by build-release.sh currently throws error ` git: command not found`.

Fixed it by adding git in the Dockerfile and loading the image in the script.

Changelog-None.
2024-05-24 15:07:39 -05:00
ShahanaFarooqui
0a163c456f docker: Adding Docker release action 2024-05-24 14:45:31 -05:00
Alex Myers
c9f7b78473 meta: update python versions to 24.05
Changelog-None
2024-05-23 18:09:03 -05:00
Alex Myers
d9213c305b Meta: update the changelog for 24.05rc1 2024-05-23 18:09:03 -05:00
Se7enZ
21a27cef16 doc: Including docs references for addpsbtoutput where it seems to be missing 2024-05-23 15:55:57 -05:00
Se7enZ
e5a1d9331f msggen: Include AddPsbtOutput to RPC list and meta field map; regenerate libraries 2024-05-23 15:55:57 -05:00
Lagrang3
428b23c975 renepay: relax knowledge mod
Add a payment mod that relaxes the knowledge of the uncertainty network
as a function of time.

Signed-off-by: Lagrang3 <lagrang3@protonmail.com>
2024-05-23 15:15:57 -05:00
Lagrang3
2664faea38 renepay: put global variables into renepayconfig.h
Signed-off-by: Lagrang3 <lagrang3@protonmail.com>
2024-05-23 15:15:57 -05:00
Rusty Russell
6b91497223 common: make gossmap ignore redundant channel_announcements.
This seems to be happening to some people, so don't panic.  Unfortunately we don't have
a good error callback here, so msg to stderr.

Fixes: https://github.com/ElementsProject/lightning/issues/7249
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-05-23 20:23:36 +02:00
Rusty Russell
744116e501 gossipd: make extra-sure we don't put in redundant channel_announcement messages.
We only write these in two places: one where we get a message from lightningd about
our own channel, and one where we get a reply from lightningd about a txout check.

The former case we explicitly check that we don't already have it in gossmap, so
add checks to the latter case, and give verbose detail if it's found.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-05-23 20:23:36 +02:00
nicolas.dorier
369c0c1391 Update Dockerfile and build-release.sh to PR7214 2024-05-23 10:30:15 -05:00
nicolas.dorier
738ddc66cc Use cross compile in dockerfile, fix arm32 support 2024-05-23 10:30:15 -05:00
Rusty Russell
877df5afdd lightningd: don't ignore fee limits on mutual close.
LDK will pick the *upper* limit (see: https://github.com/lightningdevkit/rust-lightning/issues/3014)!

It should not do this, but since you can set a manual range for mutual close, it's probably better to disable this option for close, as it's even more dangerous than documented.

Changelog-Changed: config/JSON: --ignore-fee-limits / setchannel ignorefeelimits no longer applies to mutual close.
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
Fixes: https://github.com/ElementsProject/lightning/issues/7242
2024-05-22 08:26:51 -05:00
Rusty Russell
9556fa5210 pytest: test that ignore-fee-limits doesn't apply for mutual close.
Thought it's intuitive, it's not documented to, and LDK's current behavior makes it quite dangerous to do so.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-05-22 08:26:51 -05:00
Vincenzo Palazzo
fbecefe5ac offer: fix type to the getchaininfo rpc
This is violate what the docs of getchainfo is telling us that the
last_block_height is a u64.

```
2024-05-17T09:53:23.464Z **BROKEN** plugin-offers: Got error reply to getchaininfo: '{\"error\":{\"code\":-1,\"data\":null,\"message\":\"invalid type: string \\\"0\\\", expected u64\"},\"id\":\"init/offers:getchaininfo#1\",\"jsonrpc\":\"2.0\"}\n\n'
2024-05-17T09:53:23.496Z INFO    plugin-offers: Killing plugin: exited before replying to init
2024-05-17T09:53:23.496Z **BROKEN** plugin-offers: Plugin marked as important, shutting down lightningd!
2024-05-17T09:53:23.496Z DEBUG   lightningd: io_break: lightningd_exit
2024-05-17T09:53:23.496Z **BROKEN** plugin-topology: Reading JSON input: Connection reset by peer
2024-05-17T09:53:23.504Z INFO    plugin-topology: Killing plugin: exited before replying to init
2024-05-17T09:53:23.504Z **BROKEN** plugin-topology: Plugin marked as important, shutting down lightningd!
2024-05-17T09:53:23.504Z DEBUG   lightningd: io_break: lightningd_exit
2024-05-17T09:53:23.504Z DEBUG   plugin-bookkeeper: Setting up database at sqlite3://accounts.sqlite3
2024-05-17T09:53:23.504Z DEBUG   connectd: REPLY WIRE_CONNECTD_START_SHUTDOWN_REPLY with 0 fds
2024-05-17T09:53:23.504Z DEBUG   lightningd: io_break: connectd_start_shutdown_reply
```

Fixing the following crash

```
Got error reply to getchaininfo: '{"error":{"code":-1,"data":null,"message":"invalid type: string \"0\", expected u64"},"id":"init/offers:getchaininfo#1","jsonrpc":"2.0"}

'lightningd: lightningd already running? Error locking PID file: Resource temporarily unavailable
```

Fixes: 847208f5d8
Changelog-None: offer: fix type to the getchaininfo rpc
Signed-off-by: Vincenzo Palazzo <vincenzopalazzodev@gmail.com>
2024-05-22 07:46:39 -05:00
Vincenzo Palazzo
4b4516c67c bcli: make last height optional
This is on me, and the last height is optional, and not required,
because sometimes you do not want wait the sync of the blockchain
but just get the information of the current status.

Signed-off-by: Vincenzo Palazzo <vincenzopalazzodev@gmail.com>
2024-05-22 07:46:39 -05:00
ShahanaFarooqui
037d269a58 doc: Updating python grpcio-tool dependency
Issue: rpc documentation on the readme server is not being updated.

It is an extension of PR #7326 to fix runtime error from github actions.

Changelog-None.
2024-05-21 20:10:13 -05:00
Aditya Sharma
7fa2e9bc60 wallet: recoverchannel RPC only stubs a channel if the id is vacant in the DB as well. Closed channels are not loaded inside the peer struct, hence find_channel_by_id fails when the id is occupied by a closed channel. So we need to create a function to directly check if the ID is occupied or not. 2024-05-21 19:21:10 -05:00
ShahanaFarooqui
425b3b02e6 doc: Adding manual trigger event
Issue: rpc documentation on the readme server is not being updated.

Updating the path from `doc/**.md` to `doc/schemas/lightning-*.json` for triggering the action because all `doc/*.7.md` files are fully generated by the `tools/fromschema.py` now.

Added manual trigger event for readme's documentation update.

Changelog-None.
2024-05-21 17:43:09 -05:00
ShahanaFarooqui
8a0a9a48f1 doc: listpeerchannel typo and description fix
Suggested by: @evansmj

In Draft PRs:
7155: doc: Clarify listpeerchannels documentation.
7156: doc: Fix two typos in documentation and schema descriptions
2024-05-21 17:43:09 -05:00
Lagrang3
abfcc9bc5d renepay: clean unit tests
Delete temporary gossmap files after unit tests completion.

Signed-off-by: Lagrang3 <lagrang3@protonmail.com>
2024-05-20 16:58:49 -05:00
Lagrang3
638fff8526 renepay: fix memleak in CI
Keep a double-entry record of pending routes so that we can flag them as
not memory leaks.

Signed-off-by: Lagrang3 <lagrang3@protonmail.com>
2024-05-20 16:58:49 -05:00
Lagrang3
4b8d9116de renepay: test channel capacity unavailable
Add a test that checks `get_route` and `uncertainty_update` behaviour's
handling of missing channel capacities.

Signed-off-by: Lagrang3 <lagrang3@protonmail.com>
2024-05-20 16:58:49 -05:00
Alex Myers
d30b1c8dc2 unit-test: update mocks 2024-05-20 16:58:49 -05:00
Niklas Gögge
123166790f common: Fix off-by-one in from_bech32_charset
`bech32_charset_rev` is only 128 bytes in size but the `c < 0 || c > 128` check allows for `c` to be equal to 128 which would be out-of-bounds. Fix this off-by-one bug by changing the check to `c >= 128`.
2024-05-18 10:02:43 +02:00
Rusty Russell
7040d49242 renepay: fix 32-bit compilation.
```
plugins/renepay/mods.c: In function 'payment_continue':
plugins/renepay/mods.c:63:7: error: cast from pointer to integer of different size [-Werror=pointer-to-int-cast]
   63 |       (u64)payment_virtual_program[payment->exec_state++];
      |       ^
```

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-05-17 14:06:36 -05:00
Rusty Russell
e03f56fe39 bcli: fix compilation on 32-bit platforms.
Reported-by: Shahana Farooqui
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-05-17 14:06:36 -05:00
Alex Myers
8a2d6fa644 doc: update rpc docs before pushing to readme
Now that our rpc documenation is generated from schema, we need to build
the docs before trying to update the rdme contents.  The goal is to fix
the following issue with the rdme-rpc-sync workflow:

Run python .github/scripts/sync-rpc-cmds.py
lightning-addgossip		lightning-addgossip.7.md
Traceback (most recent call last):
  File .github/scripts/sync-rpc-cmds.py, line 92, in <module>
    main()
  File .github/scripts/sync-rpc-cmds.py, line 82, in main
    with open(doc/ + file) as f:
FileNotFoundError: [Errno 2] No such file or directory: 'doc/lightning-addgossip.7.md'
2024-05-17 13:56:18 -05:00
Alex Myers
cbf343269b pytest: use reserve_unused_port even more
Uses the NodeFactory method to call reserve_unused_port
which replaced the ephemeral_port_reserve function. This
frees the reserved ports at teardown.
2024-05-17 13:56:18 -05:00
Vincenzo Palazzo
b5cfd981a1 docs: adds documentation about the log notification
Changelog-None: docs: adds documentation about the log notification
Signed-off-by: Vincenzo Palazzo <vincenzopalazzodev@gmail.com>
2024-05-17 13:03:12 -05:00
Vincenzo Palazzo
ce70167ead core: notify plugins when a log line is emitted.
Currently make a plugin that do reportings of logs on
a services like graphana is not possible. So this commit
include the possibility to write a plugin that do the report
of this analisys.

Changelog-Added: core: notify plugins when a log line is emitted.
Signed-off-by: Vincenzo Palazzo <vincenzopalazzodev@gmail.com>
2024-05-17 13:03:12 -05:00
daywalker90
5430b65b4c msggen: add checkrune method 2024-05-17 16:30:43 +02:00
daywalker90
b4c061798c msggen: add blacklistrune method 2024-05-17 16:30:43 +02:00
daywalker90
473694c39a msggen: add createrune method 2024-05-17 16:30:43 +02:00
daywalker90
19646f93c6 msggen: add showrunes method
Changelog-None
2024-05-17 16:30:43 +02:00
daywalker90
21446c3401 msggen: add multiwithdraw method
Changelog-None
2024-05-17 16:30:43 +02:00
daywalker90
f83732f990 msggen: add makesecret method
Changelog-None
2024-05-17 16:30:43 +02:00
Christian Decker
36ef3db762 fixup! msggen: add listconfigs method 2024-05-17 16:30:43 +02:00
daywalker90
1dd16f72fb msggen: add listconfigs method
Changelog-None
2024-05-17 16:30:43 +02:00
daywalker90
bd575b51e5 msggen: fix edge cases in rust composite field names 2024-05-17 16:30:43 +02:00
daywalker90
c98185d944 tools: allow spelling of HtlcTlv 2024-05-17 16:30:43 +02:00
daywalker90
6db56180f9 msggen: allow backfilling of already deprecated fields 2024-05-17 16:30:43 +02:00
daywalker90
c9a9d62367 msggen: add listinvoicerequests, disableinvoicerequest, invoicerequest methods
Changelog-None
2024-05-17 16:30:43 +02:00
daywalker90
6acfca7517 msggen: add routes to decode and decodepay
Changelog-None
2024-05-17 16:30:43 +02:00
daywalker90
c8d88c9130 msggen: fix invoice request missing exposeprivatechannels
Changelog-None
2024-05-17 16:30:43 +02:00
daywalker90
bd1123cf32 msggen: add help method
Changelog-None
2024-05-17 16:30:43 +02:00
daywalker90
5510445bbc msggen: add funderupdate method
Changelog-None
2024-05-17 16:30:43 +02:00
daywalker90
5047bc6dd1 msggen: add emergencyrecover, recover, recoverchannel methods
Changelog-None
2024-05-17 16:30:43 +02:00
daywalker90
16c036eed8 msggen: add dev-forget-channel method
Changelog-None
2024-05-17 16:30:43 +02:00
daywalker90
a9ff3cb039 pytests: use reserve_unused_port() everywhere
Changelog-None
2024-05-16 17:31:02 +02:00
Erik De Smedt
934b85a023 Updated poetry.lock file 2024-05-16 14:00:18 +02:00
Erik De Smedt
24ae7751cf Makefile: Include pyln-grpc proto in PYTHONPATH
When running `make check-python` we'll expclicitly include
`pyln-grpc-proto` in the `PYTHONPATH`.

This ensures we always run the tests using the version installed in
`./contrib/pyln-grpc-proto`
2024-05-16 14:00:18 +02:00
Christian Decker
b4d10a2e82 gci: Try to fix the pyln-grpc installation in CI 2024-05-16 14:00:18 +02:00
Erik De Smedt
7ba53dc828 Fix test for notification of custommsg
I forgot to add a `break` clause at the end of the test.

Without the break the test will keep waiting forever
on a `custommsg` that will never arrive
2024-05-16 14:00:18 +02:00
Erik De Smedt
f49cb2cb1a Include grpc-msg-buffer-size in docs 2024-05-16 14:00:18 +02:00
Erik De Smedt
151975b282 msggen: Allow non_camel_case for notification
In rust enum are expected to be CamelCase.
However, we are generating enum's using CAPITAL_SNAKE_CASE.

This generates a warning and breaks CI.

See `cln_rpc::notifications::ConnectAddressType::LOCAL_SOCKET`
2024-05-16 14:00:18 +02:00
Erik De Smedt
c1062b1db7 Test for notifications over grpc 2024-05-16 14:00:18 +02:00
Erik De Smedt
867465c0ed cln_rpc: Test deserialize_connect_notification 2024-05-16 14:00:18 +02:00
Erik De Smedt
83cc6c44e0 msggen: Schema for ConnectNotification + collisions
The schema in the docs for the `ConnectNotification` was faulty.
I've already fix this in https://github.com/ElementsProject/lightning/pull/7085

The new schema is

```
{
  "connect" :  {
    "address" : {
      "address" : "127.0.0.1",
      "port" : 38012,
      "type" : "ipv4"
  },
  "direction" : "in",
  "id" : "022d223620a359a47ff7f7ac447c85c46c923da53389221a0054c11c1e3ca31d59"
  }
}
```

The `address` in the `connect` field will be encoded in protobuf as
`ConnectAddress`. However, this collides with the `ConnectAddress` that
is defined in the `connect` rpc-method.

This commit
- Updates the schema in `doc/schemas/notification/connect.json`
- Changes `msggen` to include an override to `PeerConnect` for any
  notification typename that starts with `Connect`

Both have an `address` field which is a composite type. This results in
naming collisions

schema's: Updated schema for connect-notification

schema for connect notification + overrides

Override ConnectAddress to `PeerConnectAddress` in protobuf
for notifications
2024-05-16 14:00:18 +02:00
Erik De Smedt
505be716aa grpc-plugin: Implement notifications
Use the changes in the `cln-grpc`-crate to support
notifications.
2024-05-16 14:00:18 +02:00
Erik De Smedt
521ac6a12a msggen: Implement notification-server 2024-05-16 14:00:18 +02:00
Erik De Smedt
fa43d3ecfc msggen: Add notifications to proto-file 2024-05-16 14:00:18 +02:00
Erik De Smedt
05b9fc1998 msggen: Add conversions for notification pb to json 2024-05-16 14:00:18 +02:00
Erik De Smedt
686dae2b9f msggen : Add notification-messages to proto-file 2024-05-16 14:00:18 +02:00
Erik De Smedt
c5a47c3149 msggen: RequestStructs for notification-streams
I'm working to expose a stream of notifications over grpc.
This requries me to define structs that can be used to request
a stream of notifications.

These structs are all empty.
2024-05-16 14:00:18 +02:00
Erik De Smedt
6b34c722f3 cln-rpc: Test for serialization of block_added 2024-05-16 14:00:18 +02:00
Erik De Smedt
d743cf253f msggen: Add test for serialization of notifications 2024-05-16 14:00:18 +02:00
Erik De Smedt
eea9c8253b msggen: Choose better when a subfield is optional
**Problem Description**

In previous commits I introduced some new fields to `msggen`.
One example is `CustomMsgResponse` in `cln-grpc/src/notification.rs`.

```rust
pub struct CustomMsgResponse {
    #[serde(skip_serializing_if = "Option::is_none")]
    pub peer_id: Option<PublicKey>,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub payload: Option<String>,
}
```

The `peer_id` and `payload` are required parameters.
However, the generated code is still marking them as `Optional`.

This is a choice made by `msggen`. It does this because `payload` and
`peer_id` are recently added fields. By marking the field as optional
the language bindings would also work when used on an older version of
Core-Lightning.

In this scenario. Marking them as optional is overkill.
The `CustomMsgStruct` and `payload` field are created in the same
version of CoreLightning.

This commit solves this behavior.
2024-05-16 14:00:18 +02:00
Erik De Smedt
6e61dde41e msggen: Provide parent in visit-method of patch
In the next commit I'll change the behavior of `OptionalPatch`.
The changes require me to have access to the `parent` of a field.

Splitting it up in a separate commit makes it easier to review.
You can run `msggen` against this version and the previous `version`.

I've tested it. It returns exactly the same output.
2024-05-16 14:00:18 +02:00
Erik De Smedt
15276b7ff5 msggen: Add notification-structs to cln_rpc
In Core Lightning notifications are JSON-messages. This commit
introduces structs that can be used to parse the notification
messages.

Using `msggen` all required tructs are automatically generated
2024-05-16 14:00:18 +02:00
Erik De Smedt
0251b45027 msggen: Move rpc-model generator 2024-05-16 14:00:18 +02:00
Erik De Smedt
d59029b464 msggen: Cut gprc into pieces!!!
No, this isn't my last resort.

The file to generate `gprc`-bindings got quite long.
I've put it in a separate folder and cut it into smaller pieces
2024-05-16 14:00:18 +02:00
Erik De Smedt
4e93bb6d9d msggen: Add notifications to the Model
Included a `notifications`-field in the `Service` and wrote the code
to parse them.

Add block-added to utils.py
2024-05-16 14:00:18 +02:00
Erik De Smedt
745f410aa6 Add schema's notifications
I've added the schema for a couple of notifications.
2024-05-16 14:00:18 +02:00
Rusty Russell
757e6f8a9b libplugin: allow display of default values.
This means we can see the values in listconfigs, even if we haven't set
them yet.

In particular, we now see the following:

* autoclean-cycle.value_int=3600
* bitcoin-rpcclienttimeout.value_int=60
* bitcoin-retry-timeout.value_int=60
* funder-max-their-funding.value_str=4294967295sat
* funder-per-channel-min.value_str=10000sat
* funder-reserve-tank.value_str=0sat
* funder-fund-probability.value_int=100

Changelog-Changed: plugins: libplugin now shows plugin option default values (where they're non-trivial)
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-05-15 15:50:54 -05:00
Rusty Russell
6af32885fa libplugin: add test for dynamic setting values.
Serves as an example, but also shows a quirk which we fix in the next patch.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-05-15 15:50:54 -05:00
Rusty Russell
f7afe1a35f plugins: two minor things I noticed.
1. sql's dev-sqlfilename should be registered as a dev option.
2. bcli's timeout is an integer, not a string.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-05-15 15:50:54 -05:00
daywalker90
c1c67635fc msggen: add upgradewallet method
Changelog-None
2024-05-15 22:11:10 +02:00
daywalker90
8edd3d4a06 msggen: add setpsbtversion method
Changelog-None
2024-05-15 22:11:10 +02:00
daywalker90
ad31a18b1d msggen: add setconfig method
Changelog-None
2024-05-15 22:11:10 +02:00
daywalker90
5ed04c9788 msggen: add sendonionmessage method
Changelog-None
2024-05-15 22:11:10 +02:00
Rusty Russell
3c48438821 pay: fix bolt12 blinded path cltv logic.
The spec has moved a bit here: the `outgoing_cltv_value` in the final onion
is basically the blockheight now (plus the 1 block delta we give ourselves).

Also, we were doubling ours, since p->min_final_cltv_expiry was already set
to p->blindedpay->cltv_expiry_delta above.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-05-15 10:55:16 -05:00
Rusty Russell
121403b5df offers: add final node's CLTV delta in when creating blinded path payinfo.
It should probably be renamed "minimum_cltv_delta" or something.

Fixes: https://github.com/ElementsProject/lightning/issues/7179
Reported-by: @carlaKC
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-05-15 10:55:16 -05:00
Rusty Russell
8b5bf716a8 offers: use node_id not scid inside blinded path.
Without this, it was broken because our peer will no longer forward
via scids for private channels.  We could use the scid alias, but the
node id is right at hand.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-05-15 10:55:16 -05:00
Rusty Russell
847208f5d8 offers: put correct CLTV limit inside blinded paths.
At plugin startup, we don't have an accurate blockheight and can get 0!

Fixes: https://github.com/ElementsProject/lightning/issues/7161
Reported-by: @carlaKC
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-05-15 10:55:16 -05:00
Rusty Russell
f9021b6ca6 pytest: add test for paying an invoice with a one-hop blinded path.
This demonstrates a number of issues reported by Carla: no surprise
since there was no test!

(We create a one-hop blinded path when we only have private channels).

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-05-15 10:55:16 -05:00
daywalker90
abd1b5fe50 cln-plugin: fix over-escaping rpc errors 2024-05-15 13:26:02 +02:00
daywalker90
b69609b9c3 cln-plugin: Add dynamic configs and a callback for changes
Changelog-Added: cln-plugin: Add dynamic configs and a callback for changes
2024-05-15 13:26:02 +02:00
daywalker90
dab9605e1f msggen: add splice_update method 2024-05-15 12:11:18 +02:00
daywalker90
04a2ad6f8b msggen: add splice_signed method 2024-05-15 12:11:18 +02:00
daywalker90
9f9b59d45b msggen: add unreserveinputs method
Changelog-None
2024-05-15 12:11:18 +02:00
daywalker90
15f0beab6b msggen: add reserveinputs method
Changelog-None
2024-05-15 12:11:18 +02:00
Rusty Russell
dca361c5c7 pytest: test that we kick out pending transient connections too.
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-05-14 18:16:26 -05:00
Rusty Russell
155311b053 connectd: --dev-handshake-no-reply so we can test pending connections.
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-05-14 18:16:26 -05:00
Rusty Russell
a9b7402910 pytest: test dropping transient connections.
Requires a hack to exhaust connectd fds and make us close a transient.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-05-14 18:16:26 -05:00
Rusty Russell
8268df9a4b connectd: implement "transient" connections.
Currently, anything which doesn't have a live channel is considered transient.
We free this first under stress, and also if they're still connecting.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-05-14 18:16:26 -05:00
Rusty Russell
9aed594177 pytest: test fetchinvoice reply path which is not a direct peer.
Our fetchinvoice always creates a reply path which terminates at their peer,
so we need a dev overrride for that.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-05-14 18:16:26 -05:00
Rusty Russell
8714289c8c plugin/offers: connect if necessary for replying to invoice_request.
You can disable this with `fetchinvoice-noconnect`.

Changelog-EXPERIMENTAL: We will now reply to invoice_request messages even if reply path requires us to make an outgoing connection (LDK does this)
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-05-14 18:16:26 -05:00
Rusty Russell
2e1274ba76 plugins/fetchinvoice: use new generic connect-if-needed infrastructure.
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-05-14 18:16:26 -05:00
Rusty Russell
b94be330e6 plugins: generalize "connect if we can't route" logic, link into offers plugin.
We're going to dynamically connect if we need to, to reply to incoming invoice_requests.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-05-14 18:16:26 -05:00
Rusty Russell
541cc9dd1f connectd: fix exhaustion code where we pick random peer.
If we don't find one searching from our random spot in the peer table,
we're supposed to wrap, not crash!

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-05-14 18:16:26 -05:00
ShahanaFarooqui
f474585568 doc: Updating installation instructions for python plugins
Previously, we only had a single python plugin `clnrest` and the instructions were embedded under other heading.

Adding a new heading for python plugins and their installation instructions will make it easier for users to locate them.

Changelog-None.
2024-05-14 21:50:29 +02:00
Ken Sedgwick
cfcdde14d8 hsmd: support HSM_VERSION 6
Changelog-Changed: hsmd: the hsmd now supports HSM_VERSION 6

This is actually optional, everything would be ok leaving native hsmd
support at HSM_VERSION 5 instead.
2024-05-14 10:39:12 -05:00
Ken Sedgwick
eda0b28cbb hsmd: HSM_VERSION 6: get_per_commitment_point never returns secret
Changelog-Changed: hsmd: HSM_VERSION 6: get_per_commitment_point does
not imply index - 2 is revoked, makes it safe to call on any index.
2024-05-14 10:39:12 -05:00
Ken Sedgwick
37fe32aa17 hsmd: make the negotiated hsmd version available to libhsmd
Changelog-None: hsmd internals
2024-05-14 10:39:12 -05:00
Ken Sedgwick
a02cc6441a channeld: split get_per_commitment_point uses into separate functions
Changelog-None: channeld internal

This factoring makes it much clearer which callers only need the pubkey and
which only need the old_secret.

VLS has merged a workaround which prevents crashing when fetching a
per-commitment-point beyond the allowed range (the secret is just not
returned in this case.
https://gitlab.com/lightning-signer/validating-lightning-signer/-/merge_requests/643

In HSM_VERSION 6 the semantic is cleaned up; get_per_commitment_point
never returns a secret and safely be called on any commitment number.
2024-05-14 10:39:12 -05:00
Ken Sedgwick
25312630aa channeld: factor out unneeded make_revocation_msg_from_secret
Changelog-None: internal to channeld

Since we don't need a special path for early old_secrets from validate
we can factor out duplicate code.
2024-05-14 10:39:12 -05:00
Ken Sedgwick
1c65fc2633 hsmd: prune unreachable pre HSM_VERSION 5 code
Changelog-None: shouldn't affect others

HSM_MIN_VERSION is 5 which implies use of
WIRE_HSMD_REVOKE_COMMITMENT_TX; prune branches that can't happen.
2024-05-14 10:39:12 -05:00
Se7enZ
ca4710e942 bcli: Add rpcclienttimeout parameter and use max value of it and retry_timeout 2024-05-13 14:26:24 -05:00
Rusty Russell
86d2478743 common: add unit test for marginal feerate function.
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-05-13 14:06:45 -05:00
Christian Decker
24ec17126c channeld: Adjust the feerate security margin profile
The feerate security margin is a multiplicative factor applied to the
feerate of some transactions in order to guarantee that the
transaction remains publishable and has a sufficient chance of being
confirmed, that we can base some of our decisions on that.

The multiplicative factor is >=1 and was so far a constant 2. This
might have been sensible in the low-fee environment, where the fees
are expected to oscillate, and almost guaranteeing that we will
eventually have rising feerates but in high-fee environments that is
no longer the case, and the 100% margin that the multiplicator 2
brings is excessive. We therefore opt to start out with 100%, then
linearly interpolate up to a given maxfeerate (which does not have to
be a real feerate ever reached, it just indicates the feerate after
which we apply the constant 10% margin.

Fixes #6974
Closes #6976
[Fixed up all the other changes required, including spendable calcualtion
 comments and unit test and pytest tests --RR]
2024-05-13 14:06:45 -05:00
daywalker90
047faf1d34 msggen: add sendinvoice method
Changelog-None
2024-05-13 20:06:40 +02:00
daywalker90
54e1c78e46 msggen: add renepaystatus method
Changelog-None
2024-05-13 20:06:40 +02:00
daywalker90
9538ecccad msggen: add renepay method
Changelog-None
2024-05-13 20:06:40 +02:00
daywalker90
5c0f25f916 msggen: add plugin method
Changelog-None
2024-05-13 20:06:40 +02:00
Rusty Russell
8027922cd4 devtools: make bolt12-cli print blinded paths properly.
Print the first_node_id field, and do it all on one line per path.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-05-12 19:11:43 -05:00
Rusty Russell
e338452c19 offers: handle scid in blinded reply path first_node_id field.
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
Changelog-EXPERIMENTAL: offers: we now understand blinded paths which use a short-channel-id(+direction) as entry point.
2024-05-12 19:11:43 -05:00
Rusty Russell
cb2c4963f2 bolt12: allow first_node_id in blinded path to be a scid.
We don't actually support it yet, but this threads through the type change,
puts it in "decode" etc.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-05-12 19:11:43 -05:00
Rusty Russell
1b9b160108 common: move json_to_blinded_path into its own file.
It's fairly obscure, and let's not make everyone link it.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-05-12 19:11:43 -05:00
Rusty Russell
7eb72c5924 plugins/fetchinvoice: remove "blindedpath" command altogether, since we're the only user.
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-05-12 19:11:43 -05:00
Rusty Russell
3e37a755cd lightningd: move undocumented "blindedpath" command into fetchinvoice plugin.
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-05-12 19:11:43 -05:00
Rusty Russell
e30c835f72 common: add sciddir_or_pubkey type.
This is proposed to be added to bolt 12, so we need a type to
represent it.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-05-12 19:11:43 -05:00
Vincenzo Palazzo
081a2eef6c docs: fixing the json response in documentation
Signed-off-by: Vincenzo Palazzo <vincenzopalazzodev@gmail.com>
2024-05-09 23:19:29 -05:00
Alex Myers
370eb73775 pytest: fix flake in test_splice_disconnect_sig
This test was failing CI under valgrind.  Allow l1 to process
incoming signatures before killing.
2024-05-09 16:14:23 -05:00
Alex Myers
840374653a pytest: fix flake in test_rbf_non_last_mined
A race condition seemed to be redirecting rpc before bitcoind processed
the second rbf transaction.
2024-05-09 16:14:23 -05:00
Alex Myers
4bcca301b0 pytest: update bookkeeper chan lease fee
Removing the min_witness_weight saves the lessor 6 sats.

lessor's DF tx vout:
"value": 4.99492248   ->   "value": 4.99492254
2024-05-09 16:14:23 -05:00
Alex Myers
231a3bd9e8 pytest: update dual-fund tests
removing min-witness-weight requirement
2024-05-09 16:14:23 -05:00
Alex Myers
db3d9e9250 dualopend: remove min_witness_weight requirement
Also fix move on uninitialized value
2024-05-09 16:14:23 -05:00
Rusty Russell
5d061c4cf4 global: remove tags from BOLT quotes now dual-funding is in master
A few of them had minor wording changes, too.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-05-09 16:14:23 -05:00
Rusty Russell
68da238b31 multifundchannel: where does this minimum weight appear in the BOLTs?
I can't find such a quote, and I'm not sure if this is correct?

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-05-09 16:14:23 -05:00
Rusty Russell
7261810bd2 openingd: be more flexible in allowing unknown segwit inputs.
Spec says exactly what to test.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-05-09 16:14:23 -05:00
Rusty Russell
310f147cc8 lightningd, dualopend: update minimum RBF increment from 1/64 to 1/24.
Seems like the final spec got a bit stricter.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-05-09 16:14:23 -05:00
Rusty Russell
8b8f703db3 dualopend: make is_dust test match the spec.
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-05-09 16:14:23 -05:00
Rusty Russell
a9dffcb1e4 common: don't set DF feature in invoices.
Merged spec says:

```
| 28/29 | `option_dual_fund`                | Use v2 of channel open, enables dual funding              | IN       |
```

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-05-09 16:14:23 -05:00
Rusty Russell
2cb6da14fb BOLT: catch up now Dual-funding is included.
Mainly we don't need to patch the spec anywhere near as much.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-05-09 16:14:23 -05:00
Rusty Russell
cca784c9d0 BOLT: update to include 2016 for max_htlc_cltv.
And deprecate the --max-locktime-blocks which allows them to set it.

Hilariously, the spec misspells CLTV as CTLV at one point, so we work around it for now.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-05-09 16:14:23 -05:00
Rusty Russell
bbb6fd4413 BOLTs: catch up with minor clarifications.
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-05-09 16:14:23 -05:00
Rusty Russell
ac3c178587 global: fix up quotes which are now in the master branch.
1. onion-message
2. blinded-payments
3. route-blinding
4. channel-type
5. warnings.

Now they'll be checked correctly, and if the spec changes, we'll know
to reexamine this code.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-05-09 16:14:23 -05:00
Rusty Russell
f0d9fc6b2e pytest: relax test_low_fd_limit for Github CI.
We expect:
	UNUSUAL.*WARNING: we have 1 channels but can file descriptors limited to 65536

We get:
	lightningd: WARNING: we have 1 channels but can file descriptors limited to 32768!

This is strange, since the first line is from Python's hard limit.  Presumably something is restricting the fd limit of children

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-05-09 01:23:46 -05:00
Rusty Russell
9c9b6dd5f8 lightningd: hell, let's start with 64k fds.
They're cheap.  The 2x channels heuristic is nice, but does assume
they restart every so often.  If someone hits 64k connections I would
like to know anyway!

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-05-09 01:23:46 -05:00
Rusty Russell
80f1063dee lightningd: increase fd limit if we can, to double number of starting channels.
1024 is a common limit, and people are starting to hit that many channels, so we should increase it: twice the number of channels seems reasonable, though we only do this at restart time.

Changelog-Changed: lightningd: we now try to increase the number of file descriptors, if it's less than twice the number of channels at startup (and log if we cannot!).
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-05-09 01:23:46 -05:00
Rusty Russell
d3dbcf03fa channeld: close an unimportant connection when fds get low.
We use a crude heuristic: if we were trying to contact them, it's a
"deliberate" connection, and should be preserved.

Changelog-Changed: connectd: prioritize peers with channels (and log!) if we run low on file descriptors.
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-05-09 01:23:46 -05:00
Rusty Russell
6a648fd2bc connectd: use hash table, not linked list, for connecting structs.
I thought I was going to want to have a convenient way of counting
these, but it turns out unnecessary.  Still, this is slightly more
efficient and simple, so I am including it.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-05-09 01:23:46 -05:00
Rusty Russell
857c0042ef lightningd: log when we fail to get an fd from hsmd.
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-05-09 01:23:46 -05:00
Rusty Russell
3bfe622413 connectd: log when we fail to receive an fd from lightningd.
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-05-09 01:23:46 -05:00
Rusty Russell
c8c87e2bf6 connectd: log if we fail an accept() call.
This can happen if we're totally out of fds, but previously we gave
no log message indicating this!

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-05-09 01:23:46 -05:00
Rusty Russell
c1ee8e4981 ccan: update to get extended ccan/io error callbacks.
So we can log when we hit fd limits on accept/recvmsg.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-05-09 01:23:46 -05:00
Rusty Russell
f34b63ff4d Typo fixes from Alex's review
Co-authored-by: Alex Myers <95372134+endothermicdev@users.noreply.github.com>
2024-05-08 23:18:27 -05:00
Christian Decker
c5faae4d71 pay: Enable chainlag offset in direct override paymod 2024-05-08 23:18:27 -05:00
Christian Decker
9d8cfcf4cf pytest: Remove outdated tests
These tests were related to sending early payments, and will now fail,
as the underlying behavior changed.
2024-05-08 23:18:27 -05:00
Christian Decker
ff0b7488eb pay: Implement offset and chainlag computation when paying
This actually uses the `chainlag` to make unsynced payments possible.
2024-05-08 23:18:27 -05:00
Christian Decker
4d27efc039 pay: Add the chainlag to the payment
The `chainlag` is defined as the positive difference between the
height of the last block processed by the node and the best height
known by the bitcoin backend. The chainlag is positive when we are
still catching up with the blockchain, and `0` otherwise.

The `chainlag` is used as an additional offset to the CLTV values when
sending payments, allowing payments to be sent even before the chain
sync completes.
2024-05-08 23:18:27 -05:00
Christian Decker
a7f4c28f5e pay: Remove the waitheight paymod
It is getting replaced with a paymod that adjusts the chain height
used to offset all calculations from.
2024-05-08 23:18:27 -05:00
Christian Decker
c95b70d52a pytest: Add a test for the height mismatch logic 2024-05-08 23:18:27 -05:00
Lagrang3
7335777595 renepay: fix some memory leaks 2024-05-08 22:32:13 -05:00
Lagrang3
7b18056b09 renepay: fix sources 2024-05-08 22:32:13 -05:00
Lagrang3
985a01b41d renepay: wake-up result collector every 50msec 2024-05-08 22:32:13 -05:00
Lagrang3
014e32ca2f renepay: a bit more verbose information in logs 2024-05-08 22:32:13 -05:00
Lagrang3
e97e6ede41 renepay: update test files 2024-05-08 22:32:13 -05:00
Lagrang3
16d00e09ef renepay: bug fix, local channel information
Listpeerchannels would update the local channel information setting the
liquidity in the outgoing channel to known_min=known_max=capacity,
when in fact it should be known_min=known_max=spendable.
2024-05-08 22:32:13 -05:00
Lagrang3
4adf9b4080 renepay: bug fix on the routebuilder
The route-builder checks the liquidity bounds of each route one at a
time. Every route that satisfy the contraints is recorded in the
uncertainty network and produces an HTLC burden on the channels it uses,
so that the following routes cannot count on the same liquidity twice.
2024-05-08 22:32:13 -05:00
Lagrang3
da00cae30b renepay: remove payment from route
Routes contain only routing information and the payment they're linked
to can be obtained through the payment_hash. We remove the dependency of
route building routines from the payment itself. In order to make
plain payment information available we define a payment_info structure.
2024-05-08 22:32:13 -05:00
Lagrang3
ca2b4e54ae renepay: add disabledmap abstraction
Define a new object called disabledmap that carries information about
the disabled channels and nodes.
2024-05-08 22:32:13 -05:00
Lagrang3
96bd0e455b renepay: refactor routefail
- use switch case over all possible WIRE_* errors,
- remove the virtual machine for routefail, use a simple two step
  solution: 1. update the gossip and 2. handle error cases
2024-05-08 22:32:13 -05:00
Lagrang3
cafc08be1d renepay: disable channels not in chan_extra_map
Expand the disabled set to include channels that are not present in the
chan_extra_map/uncertainty network.
2024-05-08 22:32:13 -05:00
Lagrang3
d2c44fc3df renepay: add a test for routehints 2024-05-08 22:32:13 -05:00
Lagrang3
761c295199 renepay: uncertainty network update revisited
- Update the uncertainty network with the gossmap+local_gossmods,
- ignore channels that fail to give their capacity.
2024-05-08 22:32:13 -05:00
Lagrang3
9f13621de9 renepay: pay selfpayments on spot
Resolve a selfpayment right from the result of `sendpay` instead of
waiting for the notification.
2024-05-08 22:32:13 -05:00
Lagrang3
fa199e21d2 renepay: minor fixes 2024-05-08 22:32:13 -05:00
Lagrang3
0e2660733f renepay: update unit tests 2024-05-08 22:32:13 -05:00
Lagrang3
13a2828b12 renepay: add a test for concurrent payments 2024-05-08 22:32:13 -05:00
Lagrang3
1ee157f02b renepay: update the Makefile 2024-05-08 22:32:13 -05:00
Lagrang3
cc00d509b1 renepay: add a helper module json.c 2024-05-08 22:32:13 -05:00
Lagrang3
73c6142965 renepay: add error codes
Using enum renepay_errorcode simplifies the low level API of chan_extra and flow.
We can extract information about the nature of a function call failure
from its return value.
2024-05-08 22:32:13 -05:00
Lagrang3
7584629696 renepay: add routefail.c
Routefail consist mainly of an API `routefail_start` that handles the
failure of a forwarding request (encoded in a route). Internally there
is a routefail datastructure that goes through a series of execution
steps, eg. updating the gossmap, updating the uncertainty network, etc.
2024-05-08 22:32:13 -05:00
Lagrang3
480dec58f2 renepay: add routetracker.c
Routetracker is a structure that is used to follow the progress of the
route forwarding requests.
2024-05-08 22:32:13 -05:00
Lagrang3
84651fa4ba renepay: add routebuilder.c
Routebuilder constitute the module that builds the routes we try in the
payment. The public API is simply `get_routes`, it replaces the similar
interface for pay_flows.
2024-05-08 22:32:13 -05:00
Lagrang3
6766acbcdf renepay: payment state machine (mods)
Add a new implementation of the payment state machine.
This is based in the `pay` plugin concept of payment modifiers,
but here we take it to the next level.
The payment goes through a virtual machine that includes calling
functions and evaluating conditions.
2024-05-08 22:32:13 -05:00
Lagrang3
4b9fe23293 renepay: the plugin executable is main.c
- move the plugin executable from pay.c to main.c,
- adapt the plugin main program to handle concurrent pay calls,
2024-05-08 22:32:13 -05:00
Lagrang3
190649585f renepay: THE plugin global structure
The plugin global structure is now defined in payplugin.h
2024-05-08 22:32:13 -05:00
Lagrang3
7ffb722b27 renepay: refactor uncertainty API
The uncertainty structure is updated based on the result of a route,
previously chan_extra and pay_flow were used instead.
2024-05-08 22:32:13 -05:00
Lagrang3
2a4a23a362 renepay: rename uncertainty_network for uncertanty 2024-05-08 22:32:13 -05:00
Lagrang3
4c91bc0ef0 renepay: abandon pay_flow for route
The role of the structure pay_flow is not taken by a new structure
called route.
2024-05-08 22:32:13 -05:00
Lagrang3
ba54d678bc renepay: concurrent pay calls
Refactor the payment structure to handle multiple pay requests for the
same or different invoices.
2024-05-08 22:32:13 -05:00
Lagrang3
3cbbaa7ab5 renepay: separate flow and chan_extra
Flow and chan_extra are two different concepts, we keep their
definitions and APIs separate.
2024-05-08 22:32:13 -05:00
Vincenzo Palazzo
e8372e7481 plugin: notify only the plugins with init state
This is fixing a bug that @chrisguida reported,
when we notify a plugin we also notify a plugin
that it is in the middle of initialization.

So imagine the following use case:

- 1. Plugin A sends get manifest
- 2. cln makes a check and generates a warning
- 3. Plugin A is subscribed to the warning or * notification
- 4. Core Lightning gets upset because it receives a warning message but it was waiting for a init.

I think it is still a bug in how Core Lightning handles the init, but also I think we should communicate with the plugin only if it is initialized.

```
lightningd-1 2024-04-23T23:20:34.154Z DEBUG   plugin-clnrest: Notification: {'warning': {'level': 'warn', 'time': '1713914433.818230531', 'timestamp': '2024-04-23T23:20:33.818Z', 'source': 'plugin-bookkeeper', 'log': \"topic 'utxo_deposit' is not a known notification topic\"}}
lightningd-1 2024-04-23T23:20:34.154Z DEBUG   hsmd: new_client: 0
lightningd-1 2024-04-23T23:20:34.154Z **BROKEN** plugin-test_libplugin: Did not receive 'init' yet, but got 'warning' instead
lightningd-1 2024-04-23T23:20:34.155Z INFO    plugin-test_libplugin: Killing plugin: exited before we sent init
lightningd-1 2024-04-23T23:20:34.155Z **BROKEN** plugin-test_libplugin: Plugin marked as important, shutting down lightningd!
lightningd-1 2024-04-23T23:20:34.155Z DEBUG   lightningd: io_break: lightningd_exit
lightningd-1 2024-04-23T23:20:34.155Z DEBUG   lightningd: io_loop: connectd_init
Time-out: can't find [re.compile('Server started with public key')] in logs
{'github_repository': 'ElementsProject/lightning', 'github_sha': '014c1eb383b0a65394cf166b3aa0174cf2077896', 'github_ref': 'refs/pull/7258/merge', 'github_ref_name': 'HEAD', 'github_run_id': 8808124001, 'github_head_ref': 'cguida/onchain_notif', 'github_run_number': 9395, 'github_base_ref': 'master', 'github_run_attempt': '1', 'testname': 'test_self_disable', 'start_time': 1713914432, 'end_time': 1713914612, 'outcome': 'fail'}
----------------------------- Captured stderr call -----------------------------
Did not receive 'init' yet, but got 'warning' insteadlightningd: lightningd/connect_control.c:767: connectd_init: Assertion `ret == ld->connectd' failed.
lightningd: FATAL SIGNAL 6 (version 014c1eb-modded)
0x555b1dc2d6f3 send_backtrace
	common/daemon.c:33
0x555b1dc2d8de crashdump
	common/daemon.c:75
0x7fda4584251f ???
	???:0
0x7fda458969fc ???
	???:0
0x7fda45842475 ???
	???:0
0x7fda458287f2 ???
	???:0
0x7fda4582871a ???
	???:0
0x7fda45839e95 ???
	???:0
0x555b1db98f8e connectd_init
	lightningd/connect_control.c:767
0x555b1dbb0307 main
	lightningd/lightningd.c:1249
0x7fda45829d8f ???
	???:0
0x7fda45829e3f ???
	???:0
0x555b1db6fd64 ???
	???:0
0xffffffffffffffff ???
	???:0
```

Reported-by: @chrisguida
Co-Developed-by: @chrisguida
Signed-off-by: Vincenzo Palazzo <vincenzopalazzodev@gmail.com>
2024-05-08 21:57:37 -05:00
Rusty Russell
1c3312c8ac pytest: clean up tests/test_db.py::test_last_tx_psbt_upgrade
Ignore bad gossip, and use the broken_log option rather than manually filtering logs.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-05-08 21:54:50 -05:00
Rusty Russell
61cc3aa887 pytest: catch more broken messages in test_important_plugins.
This can happen, so allow them.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-05-08 21:54:50 -05:00
Rusty Russell
92c28a5bcd Add missing docs and Changelog-Added line.
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
Changelog-Added: Config: new log level `trace` where we moved the very noisiest `debug` logs.
2024-05-08 21:05:49 -05:00
Ken Sedgwick
5b2c237718 drive-by: fix valgrind complaint about uninitialized memory 2024-05-08 21:05:49 -05:00
Ken Sedgwick
e93ad5d124 logging: move noisy gossip recv message to TRACE
```
lightningd-test   | 2024-04-26T13:07:01.581Z DEBUG   031c64a68e6d1b9e50711336d92b434c584ce668b2fae59ee688bd73713fee1569-gossipd: handle_recv_gossip: WIRE_CHANNEL_UPDATE
lightningd-test   | 2024-04-26T13:07:01.581Z DEBUG   031c64a68e6d1b9e50711336d92b434c584ce668b2fae59ee688bd73713fee1569-gossipd: handle_recv_gossip: WIRE_CHANNEL_UPDATE
lightningd-test   | 2024-04-26T13:07:01.582Z DEBUG   031c64a68e6d1b9e50711336d92b434c584ce668b2fae59ee688bd73713fee1569-gossipd: handle_recv_gossip: WIRE_CHANNEL_UPDATE
```
2024-05-08 21:05:49 -05:00
Ken Sedgwick
788e102482 logging: move two noisy plugin_hook logging entries to TRACE
These are very noisy at the debug level:
DEBUG   lightningd: Calling rpc_command hook of plugin clboss
DEBUG   lightningd: Plugin clboss returned from rpc_command hook call

As seen in https://github.com/ZmnSCPxj/clboss/issues/194
2024-05-08 21:05:49 -05:00
Ken Sedgwick
e3c600b0c8 logging: add TRACE between DEBUG and IO
By moving super-noisy debugging logging to new TRACE level we can
make long-term logging at DEBUG possible w/o removing any logging.

Addresses ([#7279])

Related Issues:
https://github.com/ElementsProject/lightning/issues/6927
https://github.com/chrisguida/smaug/issues/34
https://github.com/ZmnSCPxj/clboss/issues/194
2024-05-08 21:05:49 -05:00
Alex Myers
c3280676e8 lightningd: avoid crash from hsmd not signing anchor spend
Temporary patch to avoid issue #6973

[ Add much more logging! --RR ]

Changelog-Fixed: lightningd: avoid crash on signing failure when trying to spend anchor outputs.
2024-05-07 16:41:47 -05:00
Rusty Russell
a481dbcddd pytest: attempt to reproduce hsm signing failure.
This didn't trigger the bug, but worth explicitly testing: we spend a
to-remote output from a previous unilateral close, to spend an anchor
on a current unilateral close.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-05-07 16:41:47 -05:00
ShahanaFarooqui
e38c828bf0 docker: Fix jq installation error for focal
`jq` is not available in the default repositories of the Ubuntu Focal image. To resolve this, adding the official jq package repository and then installing it.

Changelog-None.
2024-05-06 22:13:54 -05:00
Rusty Russell
153567d699 pytest: test that the preapprove hooks get called by check.
We add a dev flag so we can decline them.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-05-06 20:51:19 -05:00
Rusty Russell
68c4b83ab1 pay: move preapproveinvoice command out so it can be called bu check.
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
Changelog-Added: JSON-RPC: `check` `keysend` now checks with HSM that it will approve it.
2024-05-06 20:51:19 -05:00
Rusty Russell
e1034eec43 keysend: move preapprovekeysend outside pay loop, so it can be called by check.
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
Changelog-Added: JSON-RPC: `check` `keysend` now checks with HSM that it will approve it.
2024-05-06 20:51:19 -05:00
Rusty Russell
c7339ea310 pytest: test various preapprove scenarios.
We wire through --dev options into the hsmd, and test preapprove accept and deby
with both old and new protocols.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-05-06 20:51:19 -05:00
Rusty Russell
bd6cf99e4d lightningd: extend preapproveinvoice and preapprovekeysend to check with HSM.
If they support it, we can actually ask hsmd when we are called in
check mode.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-05-06 20:51:19 -05:00
Rusty Russell
6ea95da342 hsmd: add variant of preapprove commands to have it check only, not do anything.
Apparently VLS actually does something when we preapprove: if caller is just
checking we want to tell it not to do that!

I put in a flag so we can test both old and new APIs.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-05-06 20:51:19 -05:00
Rusty Russell
33cfef84d8 hsmd: add preinit message to set HSM dev flags.
This should make VLS's life easier: they can ignore dev flags they
don't understand, but we will know their capabilites after init and so
know what they didn't understand (if required).

The only flag for now is a flag to force failure for "preapprove" calls.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-05-06 20:51:19 -05:00
Rusty Russell
e99f061909 setconfig: more thorough check for internal config options.
Now we can check that the setconfig would actually parse.  We do this
by handing NULL to the calback to indicate it's a test, which may not
work in general but works for now.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
Changelog-Added: `check` `setconfig` now checks that the new config setting would be valid.
2024-05-06 20:51:19 -05:00
Rusty Russell
dcbdb85497 libplugin: allow check setconfig on all dynamic options.
We need to pass through setconfig in check mode, then we need to have libplugin
add (and use!) a `check_only` parameter to all option setting.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
Changelog-Added: JSON-RPC: `check` `setconfig` on plugin options can now check the config value would be accepted.
2024-05-06 20:51:19 -05:00
Rusty Russell
03db143216 pytest: test the check command in libplugin.
For extra points, we use an async command which calls out to listdatastore
before returning.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-05-06 20:51:19 -05:00
Rusty Russell
fc21fc56dc libplugin: handle check for our commands.
We don't thoroughly handle `check setconfig`: it would be good to
allow this to do further checking!

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-05-06 20:51:19 -05:00
Rusty Russell
11ffbc305e lightningd: allow plugins to specify cancheck for us to pass check commands through.
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
Changelog-Added: Plugins: Can now opt in to handle `check` command on their commands, for more thorough checking.
2024-05-06 20:51:19 -05:00
Rusty Russell
16615f4ed5 lightningd: add optional ->check callback to struct json_command.
If this is set, instead of mangling the request in-place, we will hand
it through raw.  Plugins will use this.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-05-06 20:51:19 -05:00
Rusty Russell
cf72fb418e param: generalize check handling a little.
We want to extend it to plugins, and we want it to be allowed to be async for more power,
so rather than not completing the cmd if we're checking, do it in command_check_done()
and call it.

This is cleaner than the special case we had before, and allows check to us all the
normal jsonrpc mechanisms, especially async requests (which we'll need if we want to
hand check requests to plugins!).

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-05-06 20:51:19 -05:00
Rusty Russell
e3c4bdf209 renepay: fix gcc -O3 overzealous warning.
gcc-12 (Ubuntu 12.3.0-9ubuntu2) 12.3.0 with -O3 gives:

```
In file included from plugins/renepay/test/../mcf.c:5,
                 from plugins/renepay/test/run-arc.c:13:
ccan/ccan/tal/str/str.h: In function ‘minflow’:
ccan/ccan/tal/str/str.h:43:9: error: ‘errmsg’ may be used uninitialized [-Werror=maybe-uninitialized]
   43 |         tal_fmt_(ctx, TAL_LABEL(char, "[]"), __VA_ARGS__)
      |         ^~~~~~~~
plugins/renepay/test/../mcf.c:1565:15: note: ‘errmsg’ was declared here
 1565 |         char *errmsg;
      |               ^~~~~~
cc1: all warnings being treated as errors
```

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-05-06 20:51:19 -05:00
Rusty Russell
b22095b275 ccan: update tal so we can annote allcators as never returning NULL.
This helps with -O3 warnings on these commits.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-05-06 20:51:19 -05:00
Rusty Russell
168ecb8979 pyln-client: pass through level parameter on command notifications.
Without this, everything came out as level INFO.

Changelog-Fixed: pyln-client: Fix Plugin.notify_message() not to ignore `level` parameter.
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-05-04 11:36:23 -05:00
Erik De Smedt
f1dc64b802 cln_plugin: Support wildcard subscriptions
Adapts `cln_plugin` to make it support wildcard `*`-subscriptions.
2024-04-30 15:24:00 -05:00
Erik De Smedt
27eaa1ef44 Repro: cln-plugin cannot subscribe to wildcard "*"
This test reproduces a bug in the `cln-plugin`-crate.
Core Lightning supports a wildcard `*` that plugins can use to
subscribe to all notifications.

However, `cln-plugin` does not support this case.
It allows the developer to subscribe `*`.
But the plug-in crashes when the first notification is received
2024-04-30 15:24:00 -05:00
Erik De Smedt
95b98cf0ee cln_plugin: Example package subscribing to "*"
Creates an example package that subscribes to all notifications and logs
them. This is useful for testing the behavior of subscribing to "*".

I've also edited the Makefile to ensure that `make` builds the example
and that `make clean` removes the example
2024-04-30 15:24:00 -05:00
Alex Myers
ff7efec723 pay: ignore uncommited channels in listpeerchannels output
Uncommited channels are missing several fields which would normally be
populated by an active channel.  This simply skips them for the purposes
of finding a route.  The particular culprit was:
{
  "peer_id": "038cd9f3679d5b39bb2105978467918d549572de472f07dd729e37c7a6377d41d5",
  "peer_connected": true,
  "state": "OPENINGD",
  "owner": "lightning_openingd",
  "opener": "local",
  "to_us_msat": 8317559000,
  "total_msat": 8317559000,
  "features": [
    "option_static_remotekey",
    "option_anchors_zero_fee_htlc_tx"
  ]
}

Fixes #7197 - SEGV in direct_pay_listpeerchannels when field private missing

Changelog-Fixed: Fixed crash in pay plugin caused by parsing uncommitted dual open channels
2024-04-30 14:52:22 -05:00
Alex Myers
56d5d45448 pytest: test pay during channel open
Notably this parses the listpeerchannels output while the state is
still uncommitted, i.e., state = OPENINGD.
2024-04-30 14:52:22 -05:00
daywalker90
dc099a046c msggen: add disableoffer method 2024-04-25 14:23:30 +02:00
daywalker90
14fea4b72b msggen: add missing bkpr-* methods
Changelog-None
2024-04-25 13:21:25 +02:00
daywalker90
3189ff6a6d msggen: add getlog method
Changelog-None
2024-04-25 13:21:25 +02:00
ShahanaFarooqui
cf5e8822b9 plugin/clnrest: Adding new config param as clnrest-swagger-root
- Updated config params and plugin
- Updated documentation

Changelog-Added: Added a new configuration for clnrest plugin to change the default Swagger UI path from `/` to custom url.
2024-04-25 13:21:25 +02:00
ShahanaFarooqui
95a92b6e4b plugin/clnrest: Adding new config param as clnrest-swagger-root
- Updated config params and plugin
- Updated documentation

Changelog-Added: Added a new configuration for clnrest plugin to change the default Swagger UI path from `/` to custom url.
2024-04-24 11:13:27 -05:00
daywalker90
7317bb174f msggen: add delforward method
Changelog-None
2024-04-24 11:47:22 +02:00
daywalker90
1a2a9b0bae poetry: add pyln-grpc-proto dependency
Changelog-None
2024-04-24 11:42:32 +02:00
Peter Neuroth
9ae5c04583 bcli: change iteration order on peerlist
It is simpler to just iterate through the peerlist backwards.

Signed-off-by: Peter Neuroth <pet.v.ne@gmail.com>
2024-04-24 05:50:54 +09:30
Peter Neuroth
8894455c02 ci: Update elementsd version used for tests
Using `getblockfrompeer` requires a version equal or above 23.0.0

Signed-off-by: Peter Neuroth <pet.v.ne@gmail.com>
2024-04-24 05:50:54 +09:30
Peter Neuroth
6e3ea36976 tests: add tests for getblockfrompeer
Changelog-Changed: Plugins: bcli: Add a path that tries to fetch blocks
from a peer if we can not find them locally.

Signed-off-by: Peter Neuroth <pet.v.ne@gmail.com>
2024-04-24 05:50:54 +09:30
Peter Neuroth
e7861e836c bcli: add version check
`getblockfrompeer` was introduced in v23.0.0, we want to skip this path
if the version of bitcoind used is below that.

Signed-off-by: Peter Neuroth <pet.v.ne@gmail.com>
2024-04-24 05:50:54 +09:30
Peter Neuroth
6a9c1e6320 bcli: try to fetch block from peer if unknown
In the case that we have peers left in the peers array and that we could
not find the block yet, we ask the next peer for the desired block.

Signed-off-by: Peter Neuroth <pet.v.ne@gmail.com>
2024-04-24 05:50:54 +09:30
Peter Neuroth
08f5e17237 bcli: add peers array to the stash
We introduce the peers array that contains the known set of connected
peers for future reference in case that we couldn't find the block we
are looking for.

Signed-off-by: Peter Neuroth <pet.v.ne@gmail.com>
2024-04-24 05:50:54 +09:30
Peter Neuroth
9baa65a738 bcli: move getblock call to a separate function
We move the `geblock` call into a separate function. This allows us to
call if from various places in the future.

Signed-off-by: Peter Neuroth <pet.v.ne@gmail.com>
2024-04-24 05:50:54 +09:30
Peter Neuroth
e06c3245f5 bcli: allow non 0 exit status for getblock call
This allows us to intercept getblock on a non 0 exit when the block was
not found. We fill this with something meaningull in future commits.

Signed-off-by: Peter Neuroth <pet.v.ne@gmail.com>
2024-04-24 05:50:54 +09:30
daywalker90
448f4c0cfb msggen: add low level fundchannel methods
Changelog-None
2024-04-23 18:43:03 +02:00
daywalker90
c80a70de25 msggen: add methods autoclean-once and autoclean-status, fix bkpr-listincome
Changelog-None
2024-04-23 17:47:56 +02:00
daywalker90
e418d0c08c msggen: rust fix for methods containing '-' 2024-04-23 17:47:56 +02:00
daywalker90
2d0778ec38 msggen: add delpay method 2024-04-22 13:28:58 +02:00
ShahanaFarooqui
c8337aaf7f plugin/wss-proxy: Documentation
Changelog-Added: Add WSS Proxy server with `wss-bind-addr` and `wss-certs` configurations.
2024-04-22 09:12:09 +09:30
ShahanaFarooqui
6b837ec024 plugin/wss-proxy: Testing WSS connection 2024-04-22 09:12:09 +09:30
ShahanaFarooqui
720af34d43 plugins/wss-proxy: Plugin included in core lightning 2024-04-22 09:12:09 +09:30
ShahanaFarooqui
c0d59fe4cc plugins/wss-proxy: Adding WSS Proxy plugin 2024-04-22 09:12:09 +09:30
daywalker90
fe180e189c msggen: add low level openchannel methods
Changelog-None
2024-04-22 09:04:43 +09:30
daywalker90
70faab55e4 msggen: fix for methods that contain '_' in their name 2024-04-22 09:04:43 +09:30
Rusty Russell
a55c0d005d spelling: its listinvoices and listinvoicerequests
Not singular (though we used to have a listinvoice, removed in v0.6.1).

Reported-by: "Plant" via email
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-04-20 10:49:50 -04:00
Rusty Russell
cd7175be88 lightningd: use return value of peer_start_channeld()
It tells us if it's failed, so we should use that rather than
reporting failure twice.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-04-20 16:36:57 +09:30
Rusty Russell
86c29b6acc lightningd: trivial cleanup: use tmpctx.
No need to explicitly free this var, we can use tmpctx.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-04-20 16:36:57 +09:30
Rusty Russell
901342b50d pyln-testing: require explicit pattern for BROKEN messages.
Rather than `allow_broken_log`, we have `broken_log` which is a regex
indicating what log lines are expected.  This tightens our tests
significantly, as it will catch *unexpected* brokenness.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2024-04-20 16:36:57 +09:30
daywalker90
ada4de1588 msggen: fix walk through nested json schemas
Changelog-None
2024-04-18 18:16:30 +02:00
daywalker90
507c2de9c1 newaddr: various fixes for msggen and docs
Changelog-None
2024-04-17 14:47:52 +02:00
daywalker90
9ad5c6bc75 msggen: use field numbers from .msggen.json for rust model if available 2024-04-17 14:47:52 +02:00
daywalker90
58b78d2b32 schema: add multifundchannel generation
Changelog-None
2024-04-17 13:06:02 +02:00
daywalker90
4d306e2691 mssgen: preserve existing camel cases
an edge case like MultifundchannelChannel_idsChannel_type
was previously converted to MultifundchannelChannelIdschannelType
instead of the correct MultifundchannelChannelIdsChannelType
2024-04-17 13:06:02 +02:00
Rusty Russell
c4edec8e22 plugins/clnrest: simple wrapper to handle missing python3.
Apparently NixOS didn't have Python (sometimes!) so let's not assume.
By reusing the JSON "parsing" code from cowsay, we can self-disable
to handle this case.

Reported-by: Shahana Farooqui <shahana.farooqui@gmail.com>
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
Changelog-Fixed: Plugins: `clnrest` now correctly self-disables if Python not present at all.
2024-04-12 10:32:32 +02:00
1036 changed files with 152792 additions and 72142 deletions

16
.github/PULL_REQUEST_TEMPLATE.md vendored Normal file
View File

@ -0,0 +1,16 @@
> [!IMPORTANT]
>
> 25.09 FREEZE July 28TH: Non-bugfix PRs not ready by this date will wait for 25.12.
>
> RC1 is scheduled on _August 11th_
>
> The final release is scheduled for September 1st.
## Checklist
Before submitting the PR, ensure the following tasks are completed. If an item is not applicable to your PR, please mark it as checked:
- [ ] The changelog has been updated in the relevant commit(s) according to the [guidelines](https://docs.corelightning.org/docs/coding-style-guidelines#changelog-entries-in-commit-messages).
- [ ] Tests have been added or modified to reflect the changes.
- [ ] Documentation has been reviewed and updated as needed.
- [ ] Related issues have been listed and linked, including any that this PR closes.

View File

@ -2,6 +2,9 @@
set -e
export BITCOIN_VERSION=27.1
export ELEMENTS_VERSION=23.2.1
DIRNAME="bitcoin-${BITCOIN_VERSION}"
EDIRNAME="elements-${ELEMENTS_VERSION}"
FILENAME="${DIRNAME}-x86_64-linux-gnu.tar.gz"

View File

@ -1,8 +1,6 @@
#!/bin/bash
set -e
export DEBIAN_FRONTEND=noninteractive
export BITCOIN_VERSION=26.1
export ELEMENTS_VERSION=22.0.2
export RUST_VERSION=stable
sudo useradd -ms /bin/bash tester
@ -22,11 +20,18 @@ sudo apt-get -qq install --no-install-recommends --allow-unauthenticated -yy \
gcc-arm-none-eabi \
gettext \
git \
gnupg \
jq \
libc6-dev-arm64-cross \
libc6-dev-armhf-cross \
libev-dev \
libevent-dev \
libffi-dev \
libicu-dev \
libpq-dev \
libprotobuf-c-dev \
libsqlite3-dev \
libssl-dev \
libtool \
libxml2-utils \
locales \
@ -44,29 +49,18 @@ sudo apt-get -qq install --no-install-recommends --allow-unauthenticated -yy \
software-properties-common \
sudo \
tcl \
tclsh \
unzip \
valgrind \
wget \
xsltproc \
systemtap-sdt-dev \
zlib1g-dev
echo "tester ALL=(root) NOPASSWD:ALL" | sudo tee /etc/sudoers.d/tester
sudo chmod 0440 /etc/sudoers.d/tester
(
cd /tmp/ || exit 1
wget https://bitcoincore.org/bin/bitcoin-core-${BITCOIN_VERSION}/bitcoin-${BITCOIN_VERSION}-x86_64-linux-gnu.tar.gz
wget https://github.com/ElementsProject/elements/releases/download/elements-${ELEMENTS_VERSION}/elements-${ELEMENTS_VERSION}-x86_64-linux-gnu.tar.gz
tar -xf bitcoin-${BITCOIN_VERSION}-x86_64-linux-gnu.tar.gz
tar -xf elements-${ELEMENTS_VERSION}-x86_64-linux-gnu.tar.gz
sudo mv bitcoin-${BITCOIN_VERSION}/bin/* /usr/local/bin
sudo mv elements-${ELEMENTS_VERSION}/bin/* /usr/local/bin
rm -rf \
bitcoin-${BITCOIN_VERSION}-x86_64-linux-gnu.tar.gz \
bitcoin-${BITCOIN_VERSION} \
elements-${ELEMENTS_VERSION}-x86_64-linux-gnu.tar.gz \
elements-${ELEMENTS_VERSION}
)
"$(dirname "$0")"/install-bitcoind.sh
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- \
-y --default-toolchain ${RUST_VERSION}
@ -78,20 +72,17 @@ curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- \
# which comes from the same tree. Makes sense!
# And
# grpcio-tools-1.54.0` requires `protobuf = ">=4.21.6,<5.0dev"`
# grpcio-tools-1.69.0` requires `protobuf = ">=5.26.1,<6.0dev"`
# Now, protoc changed to date-based releases, BUT Python protobuf
# didn't, so Python protobuf 4.21.12 (in Ubuntu 23.04) corresponds to
# protoc 21.12 (which, FYI, is packaged in Ubuntu as version 3.21.12).
# So we're going to nail these versions as 21.12, which is what recent
# Ubuntu has, and hopefully everyone else can get. And this means that
# When CI checks that no files have changed under regeneration, you won't
# get a fail just because the dev's protoc is a different version.
# In general protobuf version x.y.z corresponds to protoc version y.z
# Honorable mention go to Matt Whitlock for spelunking this horror with me!
PROTOC_VERSION=21.12
PROTOC_VERSION=29.4
PB_REL="https://github.com/protocolbuffers/protobuf/releases"
curl -LO $PB_REL/download/v${PROTOC_VERSION}/protoc-${PROTOC_VERSION}-linux-x86_64.zip
sudo unzip protoc-${PROTOC_VERSION}-linux-x86_64.zip -d /usr/local/

View File

@ -2,26 +2,30 @@ import os
from time import sleep
import requests
import re
from enum import Enum
# readme url
URL = "https://dash.readme.com/api/v1/docs"
URL = "https://dash.readme.com/api/v1"
# category id for API reference
CATEGORY_ID = "63e4e160c60b2e001dd1cc4e"
CATEGORY_SLUG = "json-rpc-apis"
def checkIfDocIsPresent(title, headers):
class Action(Enum):
ADD = 'add'
UPDATE = 'update'
DELETE = 'delete'
check_url = URL + "/" + title
response = requests.get(check_url, headers=headers)
def getListOfRPCDocs(headers):
response = requests.get(f"{URL}/categories/{CATEGORY_SLUG}/docs", headers=headers)
if response.status_code == 200:
return True
return response.json()
else:
return False
return []
def publishDoc(title, body, order):
key = os.environ.get("README_API_KEY")
def publishDoc(action, title, body, order, headers):
payload = {
"title": title,
"type": "basic",
@ -30,28 +34,30 @@ def publishDoc(title, body, order):
"hidden": False,
"order": order,
}
headers = {
"accept": "application/json",
"content-type": "application/json",
"authorization": "Basic " + key,
}
isDocPresent = checkIfDocIsPresent(title, headers)
if isDocPresent:
# update doc
update_url = URL + "/" + title # title == slug
response = requests.put(update_url, json=payload, headers=headers)
if response.status_code != 200:
print(response.text)
else:
print("Updated ", title)
else:
# title == slug
if action == Action.ADD:
# create doc
response = requests.post(URL, json=payload, headers=headers)
response = requests.post(URL + "/docs", json=payload, headers=headers)
if response.status_code != 201:
print(response.text)
else:
print("Created ", title)
elif action == Action.UPDATE:
# update doc
response = requests.put(f"{URL}/docs/{title}", json=payload, headers=headers)
if response.status_code != 200:
print(response.text)
else:
print("Updated ", title)
elif action == Action.DELETE:
# delete doc
response = requests.delete(f"{URL}/docs/{title}", headers=headers)
if response.status_code != 204:
print(response.text)
else:
print("Deleted ", title)
else:
print("Invalid action")
def extract_rpc_commands(rst_content):
@ -69,19 +75,36 @@ def extract_rpc_commands(rst_content):
def main():
# define headers for requests
headers = {
"accept": "application/json",
"content-type": "application/json",
"authorization": "Basic " + os.environ.get("README_API_KEY"),
}
# path to the rst file from where we fetch all the RPC commands
path_to_rst = "doc/index.rst"
with open(path_to_rst, "r") as file:
rst_content = file.read()
commands = extract_rpc_commands(rst_content)
if commands:
commands_from_local = extract_rpc_commands(rst_content)
commands_from_readme = getListOfRPCDocs(headers)
# Compare local and server commands list to get the list of command to add or delete
commands_local_title = set(command[0] for command in commands_from_local)
commands_readme_title = set(command['title'] for command in commands_from_readme)
commands_to_delete = commands_readme_title - commands_local_title
commands_to_add = commands_local_title - commands_readme_title
for name in commands_to_delete:
publishDoc(Action.DELETE, name, "", 0, headers)
sleep(3)
if commands_from_local:
order = 0
for name, file in commands:
print(f"{name}\t\t{file}")
for name, file in commands_from_local:
with open("doc/" + file) as f:
body = f.read()
publishDoc(name, body, order)
publishDoc(Action.ADD if name in commands_to_add else Action.UPDATE, name, body, order, headers)
order = order + 1
sleep(3)
else:

View File

@ -5,28 +5,35 @@ on:
branches:
- "master"
pull_request:
workflow_dispatch:
jobs:
testfreebsd:
runs-on: macos-10.15
runs-on: ubuntu-22.04
name: Build and test on FreeBSD
timeout-minutes: 120
strategy:
fail-fast: true
matrix:
bitcoind-version: ["27.1"]
steps:
- uses: actions/checkout@v2
- uses: actions/checkout@v4
- name: Test in FreeBSD
id: test
uses: vmactions/freebsd-vm@v0.1.5
uses: vmactions/freebsd-vm@v1
with:
usesh: true
sync: rsync
copyback: false
prepare: |
pkg install -y \
bash \
wget \
py38-pip \
py38-sqlite3 \
python310 \
gmake \
git \
python \
postgresql12-server \
postgresql16-server \
autoconf \
automake \
libtool \
@ -34,38 +41,26 @@ jobs:
gettext \
sqlite3 \
lowdown \
pkgconf \
jq \
protobuf \
curl
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y --default-toolchain nightly-2021-08-3z1
python3.10 -m ensurepip
python3.10 -m pip install --upgrade pip
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y --default-toolchain stable
cd /tmp/ || exit 1
wget https://bitcoincore.org/bin/bitcoin-core-26.1/bitcoin-26.1-x86_64-linux-gnu.tar.gz
tar -xf bitcoin-26.1-x86_64-linux-gnu.tar.bz2
sudo mv bitcoin-26.1/bin/* /usr/local/bin
rm -rf \
bitcoin-26.1-x86_64-linux-gnu.tar.gz \
bitcoin-26.1
run: |
PATH=/root/.local/bin:$PATH
PATH=/root/.local/bin:$PATH:/root/.cargo/bin; export PATH
pip install --user -U wheel pip
pip install --user -U -r requirements.txt
# Install utilities that aren't dependencies, but make
# running tests easier/feasible on CI (and pytest which
# keeps breaking the rerunfailures plugin).
pip install --user -U \
blinker \
flake8 \
mako \
pytest-sentry \
pytest-test-groups==1.0.3 \
pytest-custom-exit-code==0.3.0 \
pytest-json-report
pip3 install --user poetry
poetry install
git clone https://github.com/lightning/bolts.git ../bolts
# fatal: unsafe repository ('/Users/runner/work/lightning/lightning' is owned by someone else)
git config --global --add safe.directory `pwd`
for d in libsodium libwally-core gheap jsmn libbacktrace lowdown; do git config --global --add safe.directory `pwd`/external/$d; done
git submodule update --init --recursive
./configure CC="$CC" --disable-valgrind
@ -80,8 +75,5 @@ jobs:
EOF
# Just run a "quick" test without memory checking
gmake
# Clean up to maximize rsync's chances of succeeding
gmake clean
poetry run gmake

View File

@ -20,7 +20,7 @@ env:
jobs:
prebuild:
name: Pre-build checks
runs-on: ubuntu-20.04
runs-on: ubuntu-22.04
timeout-minutes: 30
env:
BOLTDIR: bolts
@ -28,7 +28,7 @@ jobs:
fail-fast: true
steps:
- name: Checkout
uses: actions/checkout@v3
uses: actions/checkout@v4
with:
ref: ${{ github.event.pull_request.head.sha }}
fetch-depth: 0
@ -42,15 +42,42 @@ jobs:
git fetch origin ${{ github.base_ref }}
git rebase origin/${{ github.base_ref }}
- name: Set up Python 3.8
uses: actions/setup-python@v4
- name: Check changelog
env:
PR_DESCRIPTION: "${{ github.event.pull_request.body || '' }}"
EVENT_NAME: "${{ github.event_name }}"
BASE_REF: "${{ github.base_ref || 'master' }}"
run: |
echo "Event Name: $EVENT_NAME"
echo "Base Ref: $BASE_REF"
echo "PR DESCRIPTION: $PR_DESCRIPTION"
if [ "$EVENT_NAME" = "pull_request" ]; then
if [[ "$PR_DESCRIPTION" != *"Changelog-None"* && \
-z "$(git log origin/$BASE_REF..HEAD --oneline --grep='Changelog-')" && \
"$(git rev-parse --abbrev-ref HEAD)" != "$BASE_REF" ]]; then
echo "::error::'Changelog' entry is missing in all commits, and 'Changelog-None' not specified in the PR description"
exit 1
else
if [[ "$PR_DESCRIPTION" == *"Changelog-None"* ]]; then
echo "Changelog found in PR description"
else
echo "Changelog found in Commit \"$(git log origin/$BASE_REF..HEAD --oneline --grep='Changelog-')\""
fi
fi
else
echo "Not a PR event."
fi
- name: Set up Python 3.10
uses: actions/setup-python@v5
with:
python-version: 3.8
python-version: '3.10'
- name: Install dependencies
run: |
bash -x .github/scripts/setup.sh
pip install -U pip wheel poetry
poetry self add poetry-plugin-export
# Export and then use pip to install into the current env
poetry export -o /tmp/requirements.txt --without-hashes --with dev
pip install -r /tmp/requirements.txt
@ -59,6 +86,9 @@ jobs:
- name: Configure
run: ./configure --enable-debugbuild --enable-rust
- name: Check source
env:
VALGRIND: 0
PYTEST_OPTS: --timeout=1200
run: make check-source BASE_REF="origin/${{ github.base_ref }}"
- name: Check Generated Files have been updated
run: make check-gen-updated
@ -93,12 +123,12 @@ jobs:
VALGRIND: 0
steps:
- name: Checkout
uses: actions/checkout@v3
uses: actions/checkout@v4
- name: Set up Python 3.8
uses: actions/setup-python@v4
- name: Set up Python 3.10
uses: actions/setup-python@v5
with:
python-version: 3.8
python-version: '3.10'
- name: Install dependencies
run: |
@ -115,6 +145,7 @@ jobs:
run: |
set -e
pip3 install --user pip wheel poetry
poetry self add poetry-plugin-export
poetry export -o requirements.txt --with dev --without-hashes
python3 -m pip install -r requirements.txt
./configure --enable-debugbuild CC="$COMPILER" ${{ matrix.COPTFLAGS_VAR }}
@ -125,7 +156,7 @@ jobs:
mv testpack.tar.bz2 cln-${CFG}.tar.bz2
- name: Check rust packages
run: cargo test --all
- uses: actions/upload-artifact@v3
- uses: actions/upload-artifact@v4
with:
name: cln-${{ matrix.CFG }}.tar.bz2
path: cln-${{ matrix.CFG }}.tar.bz2
@ -150,12 +181,12 @@ jobs:
VALGRIND: 0
steps:
- name: Checkout
uses: actions/checkout@v3
uses: actions/checkout@v4
- name: Set up Python 3.8
uses: actions/setup-python@v4
- name: Set up Python 3.10
uses: actions/setup-python@v5
with:
python-version: 3.8
python-version: '3.10'
- name: Install dependencies
run: |
@ -163,6 +194,7 @@ jobs:
sudo apt-get update -qq
sudo apt-get install -y -qq lowdown
pip install -U pip wheel poetry
poetry self add poetry-plugin-export
# Export and then use pip to install into the current env
poetry export -o /tmp/requirements.txt --without-hashes --with dev
pip install -r /tmp/requirements.txt
@ -170,14 +202,14 @@ jobs:
git clone https://github.com/lightning/bolts.git ../${BOLTDIR}
- name: Download build
uses: actions/download-artifact@v3
uses: actions/download-artifact@v4
with:
name: cln-${{ matrix.CFG }}.tar.bz2
- name: Check
run: |
tar -xaf cln-${{ matrix.CFG }}.tar.bz2
make -j $(nproc) check-units installcheck VALGRIND=${{ matrix.VALGRIND }}
eatmydata make -j $(nproc) check-units installcheck VALGRIND=${{ matrix.VALGRIND }}
check-fuzz:
name: Run fuzz regression tests
@ -186,17 +218,18 @@ jobs:
- prebuild
steps:
- name: Checkout
uses: actions/checkout@v3
uses: actions/checkout@v4
- name: Set up Python 3.8
uses: actions/setup-python@v4
- name: Set up Python 3.10
uses: actions/setup-python@v5
with:
python-version: 3.8
python-version: '3.10'
- name: Install dependencies
run: |
bash -x .github/scripts/setup.sh
pip install -U pip wheel poetry
poetry self add poetry-plugin-export
# Export and then use pip to install into the current env
poetry export -o /tmp/requirements.txt --without-hashes --with dev
pip install -r /tmp/requirements.txt
@ -211,14 +244,12 @@ jobs:
runs-on: ubuntu-22.04
timeout-minutes: 120
env:
BITCOIN_VERSION: "26.1"
ELEMENTS_VERSION: 22.0.2
RUST_PROFILE: release # Has to match the one in the compile step
PYTEST_OPTS: --timeout=1200 --force-flaky
PYTEST_OPTS: --timeout=1200
needs:
- compile
strategy:
fail-fast: true
fail-fast: false
matrix:
include:
- NAME: gcc
@ -261,12 +292,12 @@ jobs:
EXPERIMENTAL_SPLICING: 1
steps:
- name: Checkout
uses: actions/checkout@v3
uses: actions/checkout@v4
- name: Set up Python 3.8
uses: actions/setup-python@v4
- name: Set up Python 3.10
uses: actions/setup-python@v5
with:
python-version: 3.8
python-version: '3.10'
- name: Install dependencies
run: |
@ -279,7 +310,7 @@ jobs:
run: .github/scripts/install-bitcoind.sh
- name: Download build
uses: actions/download-artifact@v3
uses: actions/download-artifact@v4
with:
name: cln-${{ matrix.CFG }}.tar.bz2
@ -312,22 +343,20 @@ jobs:
run: |
env
cat config.vars
VALGRIND=0 poetry run pytest tests/ -vvv -n ${PYTEST_PAR} ${PYTEST_OPTS}
VALGRIND=0 poetry run eatmydata pytest tests/ -vvv -n ${PYTEST_PAR} ${PYTEST_OPTS}
integration-valgrind:
name: Valgrind Test CLN ${{ matrix.name }}
runs-on: ubuntu-22.04
timeout-minutes: 120
env:
BITCOIN_VERSION: "26.1"
ELEMENTS_VERSION: 22.0.2
RUST_PROFILE: release # Has to match the one in the compile step
CFG: compile-gcc
PYTEST_OPTS: --test-group-random-seed=42 --timeout=1800 --force-flaky
PYTEST_OPTS: --test-group-random-seed=42 --timeout=1800
needs:
- compile
strategy:
fail-fast: true
fail-fast: false
matrix:
include:
- NAME: Valgrind (01/10)
@ -352,12 +381,12 @@ jobs:
PYTEST_OPTS: --test-group=10 --test-group-count=10
steps:
- name: Checkout
uses: actions/checkout@v3
uses: actions/checkout@v4
- name: Set up Python 3.8
uses: actions/setup-python@v4
- name: Set up Python 3.10
uses: actions/setup-python@v5
with:
python-version: 3.8
python-version: '3.10'
- name: Install dependencies
run: |
@ -370,7 +399,7 @@ jobs:
run: .github/scripts/install-bitcoind.sh
- name: Download build
uses: actions/download-artifact@v3
uses: actions/download-artifact@v4
with:
name: cln-compile-gcc.tar.bz2
@ -382,23 +411,21 @@ jobs:
SLOW_MACHINE: 1
TEST_DEBUG: 1
run: |
VALGRIND=1 poetry run pytest tests/ -vvv -n 3 ${PYTEST_OPTS} ${{ matrix.PYTEST_OPTS }}
VALGRIND=1 poetry run eatmydata pytest tests/ -vvv -n 3 ${PYTEST_OPTS} ${{ matrix.PYTEST_OPTS }}
integration-sanitizers:
name: Sanitizers Test CLN
runs-on: ubuntu-22.04
timeout-minutes: 120
env:
BITCOIN_VERSION: "26.1"
ELEMENTS_VERSION: 22.0.2
RUST_PROFILE: release
SLOW_MACHINE: 1
TEST_DEBUG: 1
PYTEST_OPTS: --test-group-random-seed=42 --timeout=1800 --force-flaky
PYTEST_OPTS: --test-group-random-seed=42 --timeout=1800
needs:
- compile
strategy:
fail-fast: true
fail-fast: false
matrix:
include:
- NAME: ASan/UBSan (01/10)
@ -423,27 +450,25 @@ jobs:
PYTEST_OPTS: --test-group=10 --test-group-count=10
steps:
- name: Checkout
uses: actions/checkout@v3
uses: actions/checkout@v4
- name: Set up Python 3.8
uses: actions/setup-python@v4
- name: Set up Python 3.10
uses: actions/setup-python@v5
with:
python-version: 3.8
python-version: '3.10'
- name: Install dependencies
run: |
bash -x .github/scripts/setup.sh
set -e
pip3 install --user pip wheel poetry
poetry export -o requirements.txt --with dev --without-hashes
python3 -m pip install -r requirements.txt
poetry install
pip3 install --user wheel poetry
poetry install --with dev --no-root
- name: Install bitcoind
run: .github/scripts/install-bitcoind.sh
- name: Download build
uses: actions/download-artifact@v3
uses: actions/download-artifact@v4
with:
name: cln-compile-clang-sanitizers.tar.bz2
@ -452,20 +477,177 @@ jobs:
- name: Test
run: |
poetry run pytest tests/ -vvv -n 2 ${PYTEST_OPTS} ${{ matrix.PYTEST_OPTS }}
poetry run eatmydata pytest tests/ -vvv -n 2 ${PYTEST_OPTS} ${{ matrix.PYTEST_OPTS }}
update-docs-examples:
name: Update examples in doc schemas (disabled temporarily!)
if: false
runs-on: ubuntu-22.04
timeout-minutes: 30
strategy:
fail-fast: false
env:
VALGRIND: 0
GENERATE_EXAMPLES: 1
PYTEST_OPTS: --timeout=1200
TEST_NETWORK: regtest
needs:
- compile
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Set up Python 3.10
uses: actions/setup-python@v5
with:
python-version: '3.10'
- name: Install dependencies
run: |
bash -x .github/scripts/setup.sh
pip install -U pip wheel poetry
poetry self add poetry-plugin-export
poetry export -o /tmp/requirements.txt --without-hashes --with dev
pip install -r /tmp/requirements.txt
- name: Install bitcoind
env:
TEST_NETWORK: regtest
run: .github/scripts/install-bitcoind.sh
- name: Download build
uses: actions/download-artifact@v4
with:
name: cln-compile-gcc.tar.bz2
- name: Unpack pre-built CLN
run: |
tar -xaf cln-compile-gcc.tar.bz2
- name: Test
run: |
eatmydata make -j $(nproc) check-doc-examples
min-btc-support:
name: Test minimum supported BTC v${{ matrix.MIN_BTC_VERSION }} with ${{ matrix.NAME }}
runs-on: ubuntu-22.04
timeout-minutes: 120
env:
RUST_PROFILE: release # Has to match the one in the compile step
PYTEST_OPTS: --timeout=1200
needs:
- compile
strategy:
fail-fast: false
matrix:
include:
- NAME: clang
CFG: compile-clang
TEST_DB_PROVIDER: sqlite3
COMPILER: clang
TEST_NETWORK: regtest
MIN_BTC_VERSION: '25.0'
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Set up Python 3.10
uses: actions/setup-python@v5
with:
python-version: '3.10'
- name: Install dependencies
run: |
pip3 install --user pip wheel poetry
poetry install
- name: Download Bitcoin Core
run: wget "https://bitcoincore.org/bin/bitcoin-core-${{ matrix.MIN_BTC_VERSION }}/bitcoin-${{ matrix.MIN_BTC_VERSION }}-x86_64-linux-gnu.tar.gz"
- name: Extract Bitcoin Core
run: tar -xf "bitcoin-${{ matrix.MIN_BTC_VERSION }}-x86_64-linux-gnu.tar.gz"
- name: Move Bitcoin Core Binaries
run: sudo mv bitcoin-${{ matrix.MIN_BTC_VERSION }}/bin/* /usr/local/bin/
- name: Clean Up Downloaded Bitcoin
run: rm -rf "bitcoin-${{ matrix.MIN_BTC_VERSION }}-x86_64-linux-gnu.tar.gz" "bitcoin-${{ matrix.MIN_BTC_VERSION }}"
- name: Download build
uses: actions/download-artifact@v4
with:
name: cln-${{ matrix.CFG }}.tar.bz2
- name: Unpack pre-built CLN
env:
CFG: ${{ matrix.CFG }}
run: |
tar -xaf cln-${CFG}.tar.bz2
- name: Test
env:
COMPILER: ${{ matrix.COMPILER }}
COMPAT: 1
CFG: ${{ matrix.CFG }}
SLOW_MACHINE: 1
PYTEST_PAR: 10
TEST_DEBUG: 1
TEST_DB_PROVIDER: ${{ matrix.TEST_DB_PROVIDER }}
TEST_NETWORK: ${{ matrix.TEST_NETWORK }}
LIGHTNINGD_POSTGRES_NO_VACUUM: 1
run: |
env
cat config.vars
VALGRIND=0 poetry run eatmydata pytest tests/ -vvv -n ${PYTEST_PAR} ${PYTEST_OPTS}
check-flake:
name: Check Nix Flake
runs-on: ubuntu-22.04
strategy:
fail-fast: true
steps:
- name: Checkout
uses: actions/checkout@v4
with:
submodules: 'recursive'
- name: Check Nix flake inputs
uses: DeterminateSystems/flake-checker-action@v8
- name: Install Nix
uses: cachix/install-nix-action@V27
with:
nix_path: nixpkgs=channel:nixos-24.05
- name: Check flake
run: nix flake check .?submodules=1#
gather:
# A dummy task that depends on the full matrix of tests, and
# signals successful completion. Used for the PR status to pass
# before merging.
# before merging. Needs to run even if they failed!
name: CI completion
runs-on: ubuntu-20.04
runs-on: ubuntu-22.04
needs:
- integration
- check-units
- integration-valgrind
- integration-sanitizers
- min-btc-support
- check-flake
if: ${{ always() }}
steps:
- name: Complete
env:
JOB_NAMES: "INTEGRATION CHECK_UNITS VALGRIND SANITIZERS BTC FLAKE"
INTEGRATION: ${{ needs.integration.result }}
CHECK_UNITS: ${{ needs['check-units'].result }}
VALGRIND: ${{ needs['integration-valgrind'].result }}
SANITIZERS: ${{ needs['integration-sanitizers'].result }}
DOCS: ${{ needs['update-docs-examples'].result }}
BTC: ${{ needs['min-btc-support'].result }}
FLAKE: ${{ needs['check-flake'].result }}
run: |
echo CI completed successfully
failed=""
for name in $JOB_NAMES; do
result="${!name}"
echo "$name: $result"
if [[ "$result" != "success" ]]; then
failed="yes"
fi
done
if [[ "$failed" == "yes" ]]; then
echo "One or more required jobs failed"
exit 1
fi

View File

@ -8,7 +8,7 @@ on:
jobs:
release_rust:
runs-on: ubuntu-latest
runs-on: ubuntu-22.04
steps:
- uses: actions/checkout@v4
- uses: dtolnay/rust-toolchain@stable

118
.github/workflows/docker-release.yml vendored Normal file
View File

@ -0,0 +1,118 @@
name: Build and push multi-platform docker images
on:
push:
tags:
- 'v[0-9]+.[0-9]+'
- 'v[0-9]+.[0-9]+.[0-9]+'
- 'v[0-9]+.[0-9]+[0-9a-z]+'
workflow_dispatch:
inputs:
version:
description: 'Release version'
required: true
repository-name:
description: 'Docker repository name'
default: 'elementsproject'
required: false
platforms-to-build:
description: 'List of platforms to build'
default: 'linux/amd64,linux/arm64,linux/arm/v7'
required: false
push-latest:
description: 'Push the latest tag also?'
default: 'false'
required: false
jobs:
build:
runs-on: ubuntu-22.04
steps:
- name: Checkout repository
uses: actions/checkout@v4
with:
ref: ${{ github.ref }} # Ensures the branch triggering the workflow is checked out
- name: Set up QEMU
uses: docker/setup-qemu-action@v3
- name: Setup Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Log in to Docker Hub
uses: docker/login-action@v3
with:
username: ${{ secrets.DOCKER_USERNAME }}
password: ${{ secrets.DOCKER_PASSWORD }}
- name: Set up values
id: set-values
run: |
if [[ "${{ github.event.inputs.version }}" != "" ]]; then
echo "Input version provided"
VERSION=${{ github.event.inputs.version }}
elif [[ ${{ github.ref_type }} == "tag" ]]; then
echo "This is a tag event"
VERSION=${{ github.ref_name }}
else
echo "No version provided and no tag found."
exit 1
fi
echo "VERSION=$VERSION" >> $GITHUB_ENV
if [[ "${{ github.event.inputs.repository-name }}" != "" ]]; then
REPONAME=${{ github.event.inputs.repository-name }}
else
REPONAME="elementsproject"
fi
echo "REPONAME=$REPONAME" >> $GITHUB_ENV
if [[ "${{ github.event.inputs.platforms-to-build }}" != "" ]]; then
PLATFORMS=${{ github.event.inputs.platforms-to-build }}
else
PLATFORMS="linux/amd64,linux/arm64,linux/arm/v7"
fi
echo "PLATFORMS=$PLATFORMS" >> $GITHUB_ENV
if [[ "${{ github.event.inputs.push-latest }}" == "true" ]] ||
([[ "${{ github.ref_type }}" == "tag" ]] && [[ ! "$VERSION" =~ rc ]]); then
echo "Latest true"
PUSHLATEST="true"
else
echo "Latest false"
PUSHLATEST="false"
fi
echo "PUSHLATEST=$PUSHLATEST" >> $GITHUB_ENV
TAGS="$REPONAME/lightningd:$VERSION"
if [[ "$PUSHLATEST" == "true" ]]; then
TAGS="$TAGS,$REPONAME/lightningd:latest"
fi
echo "TAGS=$TAGS" >> $GITHUB_ENV
- name: Print GitHub Ref Values
run: |
echo "GITHUB REF TYPE: ${{ github.ref_type }}"
echo "GITHUB REF NAME: ${{ github.ref_name }}"
echo "EVENT INPUT VERSION: ${{ github.event.inputs.version }}"
echo "EVENT INPUT REPO: ${{ github.event.inputs.repository-name }}"
echo "EVENT INPUT PLATFORMS: ${{ github.event.inputs.platforms-to-build }}"
echo "EVENT INPUT PUSH LATEST: ${{ github.event.inputs.push-latest }}"
echo "ENV VERSION: ${{ env.VERSION }}"
echo "ENV REPO NAME: ${{ env.REPONAME }}"
echo "ENV PLATFORMS: ${{ env.PLATFORMS }}"
echo "ENV PUSH LATEST: ${{ env.PUSHLATEST }}"
echo "ENV TAGS: ${{ env.TAGS }}"
- name: Build and push Docker image
uses: docker/build-push-action@v5
with:
context: .
file: ./Dockerfile
push: true
platforms: ${{ env.PLATFORMS }}
tags: ${{ env.TAGS }}

34
.github/workflows/docker.yml vendored Normal file
View File

@ -0,0 +1,34 @@
name: Docker packaging
on:
push:
tags:
- 'basedon-*'
jobs:
main:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
-
name: Set up QEMU
uses: docker/setup-qemu-action@v3
-
name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
-
name: Environment variables
run: env
-
name: Create images
env:
DOCKERHUB_USER: ${{ secrets.DOCKERHUB_USER }}
DOCKERHUB_PASS: ${{ secrets.DOCKERHUB_PASS }}
DOCKERHUB_REPO: ${{ vars.DOCKERHUB_REPO }}
shell: bash
run: |
LATEST_TAG=${GITHUB_REF#refs/tags/}
LATEST_TAG=${LATEST_TAG:8} #trim "basedon-" from tag
echo "$DOCKERHUB_PASS" | docker login -u "$DOCKERHUB_USER" --password-stdin
docker buildx create --use
DOCKER_BUILDX_OPTS="--platform linux/amd64,linux/arm64,linux/arm/v7 --push"
docker buildx build $DOCKER_BUILDX_OPTS -t $DOCKERHUB_REPO:$LATEST_TAG .

View File

@ -5,55 +5,58 @@ on:
jobs:
smoke-test:
name: Smoke Test macOS
runs-on: macos-latest
runs-on: macos-14
timeout-minutes: 120
strategy:
fail-fast: true
matrix:
bitcoind-version: ["27.1"]
steps:
- name: Checkout
uses: actions/checkout@v2.0.0
uses: actions/checkout@v4
- name: Download Bitcoin ${{ matrix.bitcoind-version }} & install binaries
run: |
export BITCOIND_VERSION=${{ matrix.bitcoind-version }}
export TARGET_ARCH="arm64-apple-darwin"
wget https://bitcoincore.org/bin/bitcoin-core-${BITCOIND_VERSION}/bitcoin-${BITCOIND_VERSION}-${TARGET_ARCH}.tar.gz
tar -xzf bitcoin-${BITCOIND_VERSION}-${TARGET_ARCH}.tar.gz
sudo mv bitcoin-${BITCOIND_VERSION}/bin/* /usr/local/bin
rm -rf bitcoin-${BITCOIND_VERSION}-${TARGET_ARCH}.tar.gz bitcoin-${BITCOIND_VERSION}
- name: Install dependencies
run: |
export PATH="/usr/local/opt:/Users/runner/.local/bin:/Users/runner/Library/Python/3.10/bin:$PATH"
export PATH="/usr/local/opt:/Users/runner/.local/bin:/opt/homebrew/bin/python3.10/bin:$PATH"
export BITCOIN_VERSION=26.1
brew install wget autoconf automake libtool python@3.10 gnu-sed gettext libsodium
(
cd /tmp/
wget https://storage.googleapis.com/c-lightning-tests/bitcoin-$BITCOIN_VERSION-osx64.tar.gz -O bitcoin.tar.gz
tar -xvzf bitcoin.tar.gz
sudo mv bitcoin-$BITCOIN_VERSION/bin/* /usr/local/bin
)
python3.10 -m pip install -U --user poetry wheel pip
brew install gnu-sed python@3.10 autoconf automake libtool protobuf
python3.10 -m pip install -U --user poetry==1.8.0 wheel pip mako
python3.10 -m poetry install
python3.10 -m pip install -U --user mako
ln -s /usr/local/Cellar/gettext/0.20.1/bin/xgettext /usr/local/opt
- name: Build
env:
PYTEST_PAR: ${{ matrix.PYTEST_PAR }}
PYTEST_OPTS: ${{ matrix.PYTEST_OPTS }}
NO_PYTHON: ${{ matrix.NO_PYTHON }}
COPTFLAGS: ${{ matrix.COPTFLAGS }}
NETWORK: ${{ matrix.NETWORK }}
TEST_CMD: ${{ matrix.TEST_CMD }}
TEST_GROUP_COUNT: ${{ matrix.TEST_GROUP_COUNT }}
TEST_GROUP: ${{ matrix.TEST_GROUP }}
- name: Build and install CLN
run: |
export PATH="/usr/local/opt:/Users/runner/.local/bin:/Users/runner/Library/Python/3.10/bin:/usr/local/opt:$PATH"
export LDFLAGS="-L/usr/local/opt/sqlite/lib"
export CPPFLAGS="-I/usr/local/opt/sqlite/include"
cat << EOF > pytest.ini
[pytest]
addopts=-p no:logging --color=yes --timeout=600 --timeout-method=thread --test-group-random-seed=42 --junitxml=report.xml --json-report --json-report-file=report.json --json-report-indent=2
markers =
slow_test: marks tests as slow (deselect with '-m "not slow_test"')
EOF
export CPATH=/opt/homebrew/include
export LIBRARY_PATH=/opt/homebrew/lib
python3.10 -m poetry run ./configure --disable-valgrind --disable-compat
python3.10 -m poetry run make
- name: Start bitcoind in regtest mode
run: |
bitcoind -regtest -daemon
sleep 5
- name: Generate initial block
run: |
bitcoin-cli -regtest createwallet default_wallet
bitcoin-cli -regtest generatetoaddress 1 $(bitcoin-cli -regtest getnewaddress)
sleep 2
- name: Start CLN in regtest mode
run: |
lightningd/lightningd --network=regtest --log-file=/tmp/l1.log --daemon
sleep 5
- name: Verify CLN is running
run: |
cli/lightning-cli --regtest getinfo

View File

@ -1,20 +1,22 @@
---
name: Publish Python 🐍 distributions 📦 to PyPI and TestPyPI
on:
# Only deploy if we're the result of a PR being merged
push:
workflow_dispatch:
branches:
- master
tags:
# Semantic versioning tags
- 'v[0-9]+.[0-9]+'
- 'v[0-9]+.[0-9]+.[0-9]+'
# Date style tags
- 'v[0-9]{2}.[0-9]{2}'
- 'v[0-9]+.[0-9]+[0-9a-z]+'
workflow_dispatch:
inputs:
dist-location:
description: 'Distribution location (test/prod)'
default: 'test'
required: false
jobs:
deploy:
name: Build and publish ${{ matrix.package }} 🐍
runs-on: ubuntu-20.04
runs-on: ubuntu-22.04
timeout-minutes: 120
strategy:
fail-fast: true
@ -26,65 +28,73 @@ jobs:
WORKDIR: contrib/pyln-testing
- PACKAGE: pyln-proto
WORKDIR: contrib/pyln-proto
- PACKAGE: pyln-grpc-proto
WORKDIR: contrib/pyln-grpc-proto
# Bolt packages are handled differently
#- PACKAGE: pyn-bolt1
# WORKDIR: contrib/pyln-spec/bolt1/
#- PACKAGE: pyn-bolt2
# WORKDIR: contrib/pyln-spec/bolt2/
#- PACKAGE: pyn-bolt4
# WORKDIR: contrib/pyln-spec/bolt4/
#- PACKAGE: pyn-bolt7
# WORKDIR: contrib/pyln-spec/bolt7/
steps:
- uses: actions/checkout@master
- name: Checkout repository
uses: actions/checkout@v4
with:
# Need to fetch entire history in order to locate the version tag
fetch-depth: 0
- name: Set up Python 3.8
uses: actions/setup-python@v5
with:
python-version: 3.8
- name: Install pypa/build and poetry
run: >-
python -m pip install build poetry --user
- name: Check version tag
run: >-
git describe --always --dirty=-modded --abbrev=7
git describe --tags --always --dirty=-modded --abbrev=7
- name: Build a binary wheel and a source tarball
- name: Setup Version
env:
WORKDIR: ${{ matrix.WORKDIR }}
run: |
export VERSION=$(git describe --abbrev=0).post$(git describe --abbrev=1 | awk -F "-" '{print $2}')
cd ${{ env.WORKDIR }}
make upgrade-version NEW_VERSION=$VERSION
poetry build --no-interaction
echo "VERSION=$(git describe --tags --abbrev=0).post$(git describe --tags --abbrev=1 | awk -F "-" '{print $2}')" >> $GITHUB_ENV
- name: Set up values
id: set-values
run: |
if [[ "${{ github.event.inputs.dist-location }}" != "" ]]; then
DISTLOCATION=${{ github.event.inputs.dist-location }}
elif [[ "${{ github.ref_type }}" == "tag" ]] && [[ ! "${{ github.ref_name }}" =~ rc ]]; then
DISTLOCATION="prod"
else
DISTLOCATION="test"
fi
echo "DISTLOCATION=$DISTLOCATION" >> $GITHUB_OUTPUT
echo "EVENT DISTLOCATION: ${{ github.event.inputs.dist-location }}"
echo "DISTRIBUTION LOCATION: $DISTLOCATION"
- name: Set up Python
uses: actions/setup-python@v4
with:
python-version: '3.10'
- name: Install Poetry
run: |
curl -sSL https://install.python-poetry.org | python3 -
echo "$HOME/.local/bin" >> $GITHUB_PATH
echo "PATH=$HOME/.local/bin:$PATH"
- name: Publish distribution 📦 to Test PyPI
if: github.repository == 'ElementsProject/lightning' && github.ref == 'refs/heads/master'
if: github.repository == 'ElementsProject/lightning' && steps.set-values.outputs.DISTLOCATION == 'test'
env:
POETRY_PYPI_TOKEN_TESTPYPI: ${{ secrets.TEST_PYPI_API_TOKEN }}
WORKDIR: ${{ matrix.WORKDIR }}
run: |
echo "POETRY VERSION TEST: $(poetry --version)"
echo "Pyln VERSION: $VERSION"
cd ${{ env.WORKDIR }}
python3 -m pip config set global.timeout 150
poetry config repositories.testpypi https://test.pypi.org/legacy/
make upgrade-version NEW_VERSION=$VERSION
poetry build --no-interaction
poetry publish --repository testpypi --no-interaction --skip-existing
- name: Publish distribution 📦 to PyPI
if: startsWith(github.ref, 'refs/tags/v') && github.repository == 'ElementsProject/lightning'
if: github.repository == 'ElementsProject/lightning' && steps.set-values.outputs.DISTLOCATION == 'prod'
env:
POETRY_PYPI_TOKEN_PYPI: ${{ secrets.PYPI_API_TOKEN }}
WORKDIR: ${{ matrix.WORKDIR }}
run: |
echo "POETRY VERSION PUBLISH: $(poetry --version)"
cd ${{ env.WORKDIR }}
export VERSION=$(git describe --abbrev=0)
export VERSION=$(git describe --tags --abbrev=0)
echo "Pyln VERSION: $VERSION"
make upgrade-version NEW_VERSION=$VERSION
python3 -m pip config set global.timeout 150
poetry build --no-interaction

View File

@ -6,13 +6,14 @@ on:
- 'master'
paths:
- 'doc/**'
workflow_dispatch:
jobs:
rdme-docs-sync:
runs-on: ubuntu-latest
runs-on: ubuntu-22.04
steps:
- name: Check out repo 📚
uses: actions/checkout@v3
uses: actions/checkout@v4
- name: Sync doc/getting-started/ 🚀
uses: readmeio/rdme@v8

View File

@ -5,24 +5,39 @@ on:
branches:
- 'master'
paths:
- 'doc/**.md'
- 'doc/schemas/*.json'
- 'doc/*.1.md'
- 'doc/*.5.md'
- 'doc/*.8.md'
- 'doc/lightningd-*.7.md'
- 'doc/reckless.7.md'
workflow_dispatch:
jobs:
rdme-rpc-sync:
runs-on: ubuntu-latest
runs-on: ubuntu-22.04
steps:
- name: Checkout repository
uses: actions/checkout@v3
uses: actions/checkout@v4
- name: Set up Python
uses: actions/setup-python@v2
uses: actions/setup-python@v5
with:
python-version: '3.8'
python-version: 3.9
- name: Install requests module
run: python -m pip install requests
- name: Install python modules
run: |
python -m pip install requests mako grpcio-tools
- name: Install dependencies
run: bash -x .github/scripts/setup.sh
- name: Build (including rpc .md files)
run: |
./configure --enable-debugbuild
make -j $(nproc)
- name: Set environment variable and run
env:
README_API_KEY: ${{ secrets.README_API_KEY }}
README_API_KEY: ${{ secrets.README_API_KEY }}
run: python .github/scripts/sync-rpc-cmds.py

191
.github/workflows/release.yml vendored Normal file
View File

@ -0,0 +1,191 @@
---
# https://docs.corelightning.org/docs/release-checklist
name: "Release 🚀"
on:
push:
tags:
- 'v[0-9]+.[0-9]+'
- 'v[0-9]+.[0-9]+.[0-9]+'
- 'v[0-9]+.[0-9]+[0-9a-z]+'
workflow_dispatch:
inputs:
version:
description: 'Release version'
required: true
create_release:
description: Create a draft release
default: no
type: choice
options:
- yes
- no
jobs:
check:
name: Check
outputs:
version: ${{ steps.capture.outputs.version }}
runs-on: ubuntu-24.04
steps:
- name: Git checkout
uses: actions/checkout@v4
with:
ref: ${{ github.ref }}
fetch-depth: 0
fetch-tags: true
- name: Determine version
run: |
if [[ "${{ github.event.inputs.version }}" != "" ]]; then
VERSION="${{ github.event.inputs.version }}"
elif [ "${{ github.ref_type }}" == "tag" ]; then
VERSION="${{ github.ref_name }}"
else
echo "No release version provided and no tag found."
exit 1
fi
echo "VERSION=$VERSION" >> "$GITHUB_ENV"
echo "Determined version: $VERSION"
- name: Validate release
run: tools/check-release.sh --version=${VERSION}
- name: Catpure version output
id: capture
run: echo "version=${VERSION}" >> "$GITHUB_OUTPUT"
releases:
name: Releases
needs: check
runs-on: ubuntu-24.04
strategy:
fail-fast: false # Let each build finish.
matrix:
target:
- 'bin-Fedora'
- 'bin-Ubuntu-focal'
- 'bin-Ubuntu-jammy'
- 'bin-Ubuntu-noble'
steps:
- name: Git checkout
uses: actions/checkout@v4
with:
fetch-tags: true
# tools/build-release.sh requires lowdown
- name: Prepare base environment
run: |
sudo apt-get install -y lowdown
./configure
- name: Build environment setup
run: |
distribution=$(echo ${{ matrix.target }} | cut -d'-' -f3)
echo "Building base image for ${distribution}"
sudo docker run --rm -v $(pwd):/build ubuntu:${distribution} bash -c "\
apt-get update && \
apt-get install -y debootstrap && \
debootstrap ${distribution} /build/${distribution}"
sudo tar -C ${distribution} -c . | docker import - ${distribution}
# Build Docker image
docker build -t cl-repro-${distribution} - < contrib/reprobuild/Dockerfile.${distribution}
if: contains(matrix.target, 'Ubuntu')
- name: Build release
run: tools/build-release.sh ${{ matrix.target }}
- name: Upload target artifacts
uses: actions/upload-artifact@v4
with:
path: release/
name: ${{ matrix.target }}
if-no-files-found: error
artifact:
name: Construct release artifact
needs:
- check
- releases
env:
version: ${{ needs.check.outputs.version }}
runs-on: ubuntu-24.04
steps:
- name: Merge artifacts
uses: actions/upload-artifact/merge@v4
with:
name: c-lightning-${{ env.version }}
pattern: bin-*
delete-merged: true
release:
name: Sign and prepare release draft
needs:
- check
- artifact
env:
version: ${{ needs.check.outputs.version }}
runs-on: ubuntu-24.04
steps:
- name: Git checkout
uses: actions/checkout@v4
with:
fetch-tags: true
- name: Download artifact
uses: actions/download-artifact@v4
with:
name: c-lightning-${{ env.version }}
path: release/
- name: Import GPG keys
id: gpg
uses: crazy-max/ghaction-import-gpg@v6
with:
gpg_private_key: ${{ secrets.GPG_PRIVATE_KEY }}
passphrase: ${{ secrets.GPG_PASSPHRASE }}
trust_level: 5
- name: Set default GPG key
run: echo "default-key ${{ steps.gpg.outputs.keyid }}" >> ~/.gnupg/gpg.conf
- name: Sign release
run: |
sudo apt-get install -y lowdown
./configure
tools/build-release.sh --without-zip sign
mv release/SHA256SUMS.asc${{ steps.gpg.outputs.keyid }} release/SHA256SUMS.asc
- name: Upload signed artifact
uses: actions/upload-artifact@v4
with:
name: c-lightning-${{ env.version }}
overwrite: true
path: release/
- name: Determine release data
id: release_data
run: |
VERSION=${{ env.version }}
CHANGELOG_VERSION=${VERSION#v}
echo "CHANGELOG_VERSION=$CHANGELOG_VERSION"
echo "changelog_version=$CHANGELOG_VERSION" >> "$GITHUB_OUTPUT"
CHANGELOG_TITLE=$(grep "## \[${CHANGELOG_VERSION}\]" CHANGELOG.md)
echo "CHANGELOG_TITLE=$CHANGELOG_TITLE"
echo "changelog_title=$CHANGELOG_TITLE" >> "$GITHUB_OUTPUT"
RELEASE_TITLE=$(echo $CHANGELOG_TITLE | cut -d'"' -f2)
echo "RELEASE_TITLE=$RELEASE_TITLE"
echo "release_title=$RELEASE_TITLE" >> "$GITHUB_OUTPUT"
- name: Prepare release draft
if: github.event_name == 'push' || (github.event_name == 'workflow_dispatch' && github.event.inputs.create_release == 'yes')
uses: softprops/action-gh-release@v2
with:
name: "${{ env.version }} ${{ steps.release_data.outputs.release_title }}"
tag_name: ${{ env.version }}
draft: true
prerelease: contains(env.version, "-rc")
files: release/*
fail_on_unmatched_files: true

113
.github/workflows/repro.yml vendored Normal file
View File

@ -0,0 +1,113 @@
---
# https://docs.corelightning.org/docs/repro
name: Repro Build Nightly
on:
# 05:00 Berlin, 03:00 UTC, 23:00 New York, 20:00 Los Angeles
schedule:
- cron: "0 3 * * *"
workflow_dispatch:
jobs:
ubuntu:
name: "Ubuntu repro build: ${{ matrix.version }}"
runs-on: ubuntu-22.04
strategy:
fail-fast: false # Let each build finish.
matrix:
version: ['focal', 'jammy', 'noble']
steps:
- name: Git checkout
uses: actions/checkout@v4
- name: Build environment setup - ${{ matrix.version }}
run: |
echo "Building base image for ${{ matrix.version }}"
echo "STEP=Build environment setup" >> "$GITHUB_ENV"
sudo docker run --rm -v $(pwd):/build ubuntu:${{ matrix.version }} bash -c "\
apt-get update && \
apt-get install -y debootstrap && \
debootstrap ${{ matrix.version }} /build/${{ matrix.version }}"
sudo tar -C ${{ matrix.version }} -c . | docker import - ${{ matrix.version }}
- name: Builder image setup - ${{ matrix.version }}
run: |
echo "STEP=Builder image setup" >> "$GITHUB_ENV"
docker build -t cl-repro-${{ matrix.version }} - < contrib/reprobuild/Dockerfile.${{ matrix.version }}
- name: Build reproducible image and store Git state - ${{ matrix.version }}
run: |
echo "STEP=Build reproducible image and store Git state" >> "$GITHUB_ENV"
# Create release directory.
mkdir $GITHUB_WORKSPACE/release
# Perform the repro build.
docker run --name cl-build -v $GITHUB_WORKSPACE:/repo -e FORCE_MTIME=$(date +%F) -t cl-repro-${{ matrix.version }}
# Commit the image in order to inspect the build later.
docker commit cl-build cl-repro
# Inspect the version.
docker run --rm -v $GITHUB_WORKSPACE:/repo -t cl-repro bash -c "make version > /repo/release/version.txt"
# Inspect the Git tree state.
docker run --rm -v $GITHUB_WORKSPACE:/repo -t cl-repro bash -c "\
git --no-pager status > /repo/release/git.log && \
git --no-pager diff >> /repo/release/git.log"
# Change permissions on the release files for access by the runner environment.
sudo chown -R runner $GITHUB_WORKSPACE/release
- name: Assert clean version - ${{ matrix.version }}
run: |
echo "STEP=Assert clean version" >> "$GITHUB_ENV"
echo 'Version:'
cat release/version.txt
echo -e
releasefile=$(ls release/clightning-*)
echo 'Release file:'
ls -al release/clightning-*
echo -e
if [ -n "$(cat release/version.txt | sed -n '/-modded/p')" ] || \
[ -n "$(echo $releasefile | sed -n '/-modded/p')" ]; then
echo "Git Status and Diff:"
cat release/git.log
echo -e
echo 'Error: release modded / dirty tree.'
exit 1
else
echo 'Success! Clean release.'
fi
- name: Upload release artifact - ${{ matrix.version }}
uses: actions/upload-artifact@v4
with:
name: release-${{ matrix.version }}
path: release
retention-days: 3 # Automatically delete after 3 days
- name: Send email on failure
if: ${{ failure() }}
uses: dawidd6/action-send-mail@v3
with:
server_address: smtp.gmail.com
server_port: 587
username: ${{ secrets.EMAIL_USERNAME }}
password: ${{ secrets.EMAIL_PASSWORD }}
from: ${{ secrets.EMAIL_USERNAME }}
to: ${{ vars.DISTRIBUTION_LIST }}
subject: "CI Failure: Step ${{ env.STEP }} failed for distro ${{ matrix.version }}"
convert_markdown: true
html_body: |
<html>
<body>
<p>GitHub Workflow ${{ github.workflow }} Failed! For more details, click on the action below.</p>
<strong>Failure Details:</strong><br/>
<strong>Event: </strong>${{ github.event_name }}<br/>
<strong>Job: </strong>${{ github.job }}<br/>
<strong>Distro: </strong>${{ matrix.version }}<br/>
<strong>Step: </strong>${{ env.STEP }}<br/>
<strong>Action: </strong><a href="${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}">${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}</a><br/>
</body>
</html>

18
.gitignore vendored
View File

@ -57,9 +57,9 @@ tests/plugins/test_selfdisable_after_getmanifest
# Ignore generated files
devtools/features
doc/schemas/lightning-sql.json
doc/lightning-*.7.md
doc/lightning*.[1578]
doc/schemas/sql.json
doc/*.7.md
doc/*.[1578]
doc/reckless*.[1578]
*_sqlgen.[ch]
*_wiregen.[ch]
@ -69,6 +69,9 @@ tests/node_pb2.py
tests/node_pb2_grpc.py
tests/primitives_pb2.py
tests/primitives_pb2_grpc.py
tests/autogenerate-examples-status.log
tests/autogenerate-examples.json
tests/autogenerate-examples-repeat.log
# Ignore unrelated stuff
.DS_Store
@ -79,14 +82,23 @@ compile_commands.json
# Rust targets
target
plugins/cln-grpc
plugins/clnrest
# Build directories
bionic/
focal/
jammy/
noble/
release/
.vscode/
.cache/
# Ignore release verification Sha256Sums
SHA256SUMS-*
doc/.doc_version
autogenerate-examples-status.log
# Ignore nix outputs
result
result-[0-9]*
tests/plugins/channeld_fakenet

File diff suppressed because it is too large Load Diff

13
.pre-commit-config.yaml Normal file
View File

@ -0,0 +1,13 @@
repos:
- repo: https://github.com/astral-sh/ruff-pre-commit
# Ruff version.
rev: v0.8.0
hooks:
# Run the linter.
- id: ruff
args: [ --diff ]
exclude: "contrib/pyln-grpc-proto/pyln/grpc/(primitives|node)_pb2(|_grpc).py"
# Run the formatter.
- id: ruff-format
args: [ --diff ]
exclude: "contrib/pyln-grpc-proto/pyln/grpc/(primitives|node)_pb2(|_grpc).py"

1
.version Normal file
View File

@ -0,0 +1 @@
25.05

View File

@ -1,8 +1,839 @@
# Changelog
All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
## [25.05] - 2025-06-16: "Satoshi's OP_RETURN Opinion"
This release named by Peter Neuroth (@nepet).
**WARNING**: `--experimental-splicing` is incompatible with previous CLN versions! You will not
be able to reestablish channels with older nodes at all, if this is enabled!
### Added
- Protocol: we now offer peer storage to any peers who create a channel. ([#8140])
- lsps-plugin: Added lsps0 service support. ([#8227])
- lsps-plugin: Added lsps0 client support. ([#8227])
- JSON-RPC: `listhtlcs` supports `index`, `start` and `end` parameters for pagination support. ([#8166])
- JSON-RPC: `listhtlcs` has `created_index` and `updated_index` fields. ([#8166])
- JSON-RPC: `wait` now supports the `htlcs` (`listhtlcs`) subsystem. ([#8166])
- JSON-RPC: `wait` now has separate `invoices`, `forwards` and `sendpays` objects for each subsystem. ([#8166])
- Reckless: `reckless update` updates all reckless-installed plugins. ([#8266])
- Splicing: Performing a splice on a channel with a pending splice now performs a RBF on the splice transaction. ([#8021])
- JSON-RPC: Added a new rpc command signmessagewithkey to sign input messages with keys from our wallet. ([#8226])
- HSMD: Added new wire API to sign messages with bitcoin wallet keys according to BIP137. ([#8226])
- JSON-RPC: `askrene-bias-channel` now has a `relative` option to add, rather than replace, a channel bias. ([#8277])
- sendonion: a new paramter `total_amount_msat` to make MPP payments with sendpay and sendonion compatible. ([#8015])
- Protocol: We now reply to `channel_reestablish` even on long-closed channels. ([#8162])
- JSON-RPC: `listpeerchannels` now has a `short_channel_id` parameter for just listing a specific channel. ([#8237])
- cln-grpc: Exposed NotificationStream in the server module. ([#8220])
### Changed
- Splicing: The splicing protocol is now compatible with Eclair, incompatible with previous CLN versions ([#8021])
- Protocol: We now exchange `announcement_signatures` as soon as we're ready, rather than waiting for 6 blocks (as per recent BOLT update.) ([#8136])
- Protocol: We won't forget still-opening channels after 2016 blocks, unless there are more than 100. ([#8162])
- Reckless: Accepts a source url or local directory as an argument to `reckless install`. ([#8266])
- Protocol: bitcoind peers are no longer asked for blocks if they don't store them. ([#8268])
- Protocol: DNS seeds are no longer used for peer lookup fallbacks. ([#8272])
- JSON-RPC: askrene channel bias can be set to accumulate via `askrene-bias-channel` by setting `relative=true`. ([#8072])
- Removed lightning- prefix from schemas/.json and doc/.md files. ([#8038])
- Update libwally to 1.4.0. ([#8158])
- Plugins: Log messages containing \n are now split into multiple log lines and " is no longer turned into \". ([#7013])
### Deprecated
Note: You should always set `allow-deprecated-apis=false` to test for changes.
- Config: `--experimental-peer-storage` (it's now the default). ([#8140])
- JSON-RPC: channel_state_changed notification field `old_state` value "unknown" (it will be omitted, instead). ([#8271])
- JSON-RPC: `wait` reply `details` object: use subsytem specific object instead. ([#8166])
### Removed
- RPC `listchannels` no longer includes private local channels (deprecated v23.08, disabled by default in v24.11). ([#8118])
- Plugins which didn't accept string JSON RPC fields (deprecated v23.08, disabled by default in v24.11). ([#8118])
- Default settings for flag options in plugins which aren't "false". ([#8118])
- Allowing 0/1 instead of false/true for plugin options (deprecated v23.08, disabled by default in v24.11). ([#8118])
- Config: `announce-addr-dns` (deprecated v23.08, disabled in v24.11). ([#8118])
- --bind-addr and --addr on onion addresses and local sockets (deprecated v23.08, disabled by default in v24.11). ([#8118])
- `accept-htlc-tlv-types` (deprecated v23.08, disabled by default in v24.11). ([#8118])
- Connection/disconnection/block_added notification raw fields (deprecated v23.08, disabled by default in v24.11). ([#8118])
- `listconfigs` raw listing (deprecated v23.08, disabled by default in v24.11). ([#8118])
### Fixed
- Protocol: anchors' fees are now much closer to the feerate targets. ([#8236])
- Protocol: Removed 200ms latency from sending commit/revoke messages. ([#8222])
- Emergency Recover: Encourages LND nodes to properly respond with a unilateral close. ([#8213])
- askrene: Fixed routing in high capacity channels. ([#8129])
- wallet: Fees are much closer to target feerate when doing txprepare/fundchannel. ([#8236])
- Plugins can now log events under the LOG_TRACE flag. ([#8113])
- JSON-RPC: `txprepare` with `all` as well as one or more non-all amount fields now produces a valid PSBT. ([#8236])
- Validated public keys in BOLT11 routing hints to prevent processing of malformed public keys.([#8282])
- Suppress logs from chanbackup ([#8254])
- lightningd: Trimmed overhead of tracing infrastructure. ([#8223])
- Enforced minimum witness program length of 2 bytes for fallback addresses to comply with BIP-141 and prevent invalid decodings.([#8219])
### EXPERIMENTAL
- `experimental-peer-storage` now only advertizes feature 43, not 41. ([#8135])
[#8222]: https://github.com/ElementsProject/lightning/pull/8222
[#8223]: https://github.com/ElementsProject/lightning/pull/8223
[#8021]: https://github.com/ElementsProject/lightning/pull/8021
[#8072]: https://github.com/ElementsProject/lightning/pull/8072
[#8237]: https://github.com/ElementsProject/lightning/pull/8237
[#8118]: https://github.com/ElementsProject/lightning/pull/8118
[#8162]: https://github.com/ElementsProject/lightning/pull/8162
[#7013]: https://github.com/ElementsProject/lightning/pull/7013
[#8268]: https://github.com/ElementsProject/lightning/pull/8268
[#8266]: https://github.com/ElementsProject/lightning/pull/8266
[#8272]: https://github.com/ElementsProject/lightning/pull/8272
[#8158]: https://github.com/ElementsProject/lightning/pull/8158
[#8226]: https://github.com/ElementsProject/lightning/pull/8226
[#8277]: https://github.com/ElementsProject/lightning/pull/8277
[#8113]: https://github.com/ElementsProject/lightning/pull/8113
[#8254]: https://github.com/ElementsProject/lightning/pull/8254
[#8220]: https://github.com/ElementsProject/lightning/pull/8220
[#8213]: https://github.com/ElementsProject/lightning/pull/8213
[#8136]: https://github.com/ElementsProject/lightning/pull/8136
[#8236]: https://github.com/ElementsProject/lightning/pull/8236
[#8140]: https://github.com/ElementsProject/lightning/pull/8140
[#8271]: https://github.com/ElementsProject/lightning/pull/8271
[#8166]: https://github.com/ElementsProject/lightning/pull/8166
[#8038]: https://github.com/ElementsProject/lightning/pull/8038
[#8282]: https://github.com/ElementsProject/lightning/pull/8282
[#8129]: https://github.com/ElementsProject/lightning/pull/8129
[#8135]: https://github.com/ElementsProject/lightning/pull/8135
[#8227]: https://github.com/ElementsProject/lightning/pull/8227
[#8015]: https://github.com/ElementsProject/lightning/pull/8015
[#8219]: https://github.com/ElementsProject/lightning/pull/8219
[25.05rc1]: https://github.com/ElementsProject/lightning/releases/tag/v25.05rc1
## [25.02.2] - 2025-04-22: "Onion Packet Filler Accreditation III"
Important fixes for bugs in v25.02.1.
### Fixed
- docker: Fixed broken docker image due to sqlite version not supporting an advanced query ([#8246])
[#8246]: https://github.com/ElementsProject/lightning/pull/8246
[25.02.2]: https://github.com/ElementsProject/lightning/releases/tag/v25.02.2
## [25.02.1] - 2025-04-03: "Onion Packet Filler Accreditation II"
Important fixes for bugs in v25.02.
### Fixed
- wallet: we could miss our own returned outputs on mutual closes if peer doesn't support option_shutdown_anysegwit ([#8175])
- wallet: rescan for missing close outputs in case above bug happened ([#8175])
- lightningd: incorrect spamming of log and potential crash on testnet case of duplicate HTLCs and slow closing. ([#8192])
- Protocol: Egregious anchor fee paid for unilateral close txs due to HTLC timeouts; it's not as urgent as our code made out! ([#8190])
- lightningd: occasional crash on bitcoind callback. ([#8186])
- autoclean/chanbackup: fixed tracepoint crash on large number of requests. ([#8188])
- autoclean: fixed occasional crash when tracepoints compiled in. ([#8198])
- `topology` crash on invoice creation if a peer had a really high feerate. ([#8187])
- `make` cleans up old clnrest directory prior to building and installing the new plugin. ([#8201], [#8159])
[#8186]: https://github.com/ElementsProject/lightning/pull/8186
[#8192]: https://github.com/ElementsProject/lightning/pull/8192
[#8187]: https://github.com/ElementsProject/lightning/pull/8187
[#8190]: https://github.com/ElementsProject/lightning/pull/8190
[#8175]: https://github.com/ElementsProject/lightning/pull/8175
[#8188]: https://github.com/ElementsProject/lightning/pull/8188
[#8198]: https://github.com/ElementsProject/lightning/pull/8198
[#8159]: https://github.com/ElementsProject/lightning/pull/8159
[#8201]: https://github.com/ElementsProject/lightning/pull/8201
[25.02.1]: https://github.com/ElementsProject/lightning/releases/tag/v25.02.1
## [25.02] - 2025-03-04: "Onion Packet Filler Accreditation"
This release named by @s373nZ.
### Added
- Plugins: `chanbackup` turns our peers into watchtowers and enables SCB to create penalty txns. ([#7772])
- JSON-RPC: `fetchinvoice` BIP 353 name support (`bip353`). ([#7887])
- JSON-RPC: `blacklistrune` now has an option to un-blacklist (`relist`). ([#8037])
- JSON-RPC: `setconfig` now has a `transient` flag which means it won't rewrite your config file. ([#8095])
- Plugins: New nofitications `plugin_stopped` and `plugin_started`. ([#7508])
- xpay: `xpay-slow-mode` makes xpay wait for all parts of a payment to complete before returning success or failure. ([#8094])
- Plugins: `xpay` now supports a `maxdelay` parameter for better `xpay-handle-pay` compatibility. ([#7969])
- JSON-RPC: `listpeerchannels` new output fields `their_max_total_htlc_out_msat` and `our_max_total_htlc_out_msat` as the value of `max_htlc_value_in_flight` (as of BOLT02) set by the local and remote nodes on channel creation. ([#8084])
- Config: Added support for Bitcoin `testnet4`. ([#7894])
### Changed
- clnrest: clnrest is now a rust plugin. ([#7509])
- JSON-RPC: `blacklistrune` no longer supports of runes over id 100,000,000. ([#8037])
- Splicing: User is prevented from trying to splice unsigned PSBTs, protecting against potential issues. ([#8052])
- Splicing: Stricter tests for interop with Eclair. ([#8031])
- `xpay` now populates more fields, so `listsendpays` and `listpays` show `destination` and `amount_msat` fields for xpay payments. ([#7941])
- `xpay` now gives the same JSON success return as documented by `pay` when `xpay-handle-pay` is set. ([#7938])
- JSON-RPC: With `xpay-handle-pay` set, xpay will now be used even if `pay` uses maxfeeprecent or exemptfee parameters (e.g. Zeus.) ([#7942])
- Release: Docker images are now based on Debian Bookworm. ([#7921])
- lightning-cli: Plugin descriptions in `lightning-cli help` is now more readable with interpretation of \n characters. ([#8022])
- Release: Fixed version number and version check in source release zip packages. ([#8010])
- Logging: We no longer suppress DEBUG messages from subdaemons. ([#7935])
- lightning-cli: `help` messages using new-lines is now printed properly, enhancing readability and consistency. ([#8022])
- pyln-testing: pyln-testing is now compatible with older versions of Core Lightning. ([#7173])
### Deprecated
Note: You should always set `allow-deprecated-apis=false` to test for changes.
- JSON-RPC: `listpeerchannels` value `max_total_htlc_in_msat`: use `our_max_htlc_value_in_flight_msat` instead to follow spec naming convention. ([#8084])
- Config: `rest-port`, `rest-protocol`, `rest-host` and `rest-certs` disabled by default (use `clnrest-*`, or `i-promise-to-fix-broken-api-user=rest-port.clnrest-prefix` etc and PLEASE REPORT if you need this!) ([#8089])
- Config: `max-locktime-blocks` disabled by default (use `i-promise-to-fix-broken-api-user=max-locktime-blocks` and PLEASE REPORT if you need this!) ([#8089])
### Removed
### Fixed
- lightningd: Startup time vastly improved for large nodes with pending closes and many bitcoin addresses. ([#8019])
- renepay: No longer crashes on trying a payment after xpay. ([#7979])
- connectd: `dev-no-reconnect-private` is respected on restart. ([#8104])
- cln-grpc, clnrest: Errors that cause them to stop will now log correctly. ([#8085])
- Plugins: xpay doesn't simply give up if our total amount is less than `htlc_minimum_msat` on some channel. ([#8057])
- Plugins: xpay suppresses multi-part payment if an invoice doesn't allow it (please, fix your nodes!) ([#8059])
- JSON-RPC: xpay now works through unannounced channels. ([#7937])
- onchaind: Don't die if we fail an unrelated channel with the same peer. ([#8056])
- gossipd: More sanity checks that we are correctly updating the `gossip_store` file. ([#8053])
- gossipd: Corruption in the `gossip_store` no longer causes ever-longer startup times and no gossip updates. ([#8053])
- gossmap: Don't crash on ZFS while reading `gossip_store`. ([#8053])
- lightningd: Tell plugins our bolt12 features (so our bolt12 invoices explicitly allow MPP). ([#8059])
- lightningd: Allow more time for plugin startup so slow nodes don't time out on startup. ([#8060])
- lightningd: Fixed onchaind crash when seeing unrelated txs (usually when catching up with old closes.) ([#8137])
- `xpay`: Corrected the CLTV values in blinded paths which sometimes caused spurious failures. ([#8121])
- Protocol: We now renegotiate an interrupted close, even if we don't need it, instead of sending an error. ([#8116])
- bcli: `getblockfrompeer` no longer requests the block from the first peer only. ([#8069])
- lightning-cli: Fixed "malformed response" bug. ([#7924])
- lightning-cli: Fixed access to man pages from the installed directory. ([#8077])
- Protocol: We were overzealous in pruning channels if we hadn't seen one side's gossip update yet. ([#8027])
- xpay-handle-pay: Handle null parameters passed in the "param" list. ([#7958])
- Offers: `decode` for bolt12 invoices "features" field renamed to "invoice_features" (as documentation said.) ([#8059])
- JSON-RPC: `xpay` will refuse to make a 0msat payment (0msat invoice, partial payment, or manually-set on amountless invoice). ([#8024])
- JSON-RPC: `getroutes` will refuse, not crash, if asked to find a route for 0msat. ([#8024])
- Blinded paths: offline peers no longer selected. ([#8138])
- build: Fixed linking against libsodium on macOS. ([#7908])
- Fixes Postgres driver availability for arm64 and arm32 Docker images. ([#7921])
- xpay: xpay no longer logs "Got command" at info level. ([#7933])
- contrib: `startup-regtest.sh` now only inspects the most recent run's logs for the active status of the clnrest plugin. ([#7509])
- build: libsodium configure check fixed to work with newer GCC. ([#7907])
### EXPERIMENTAL
- onchaind: Correctly collect our own (delayed) funds if we have a unilateral close when we are still offering a lease. ([#8111])
[#8138]: https://github.com/ElementsProject/lightning/pull/8138
[#8137]: https://github.com/ElementsProject/lightning/pull/8137
[#8111]: https://github.com/ElementsProject/lightning/pull/8111
[#8121]: https://github.com/ElementsProject/lightning/pull/8121
[#8116]: https://github.com/ElementsProject/lightning/pull/8116
[#8024]: https://github.com/ElementsProject/lightning/pull/8024
[#7969]: https://github.com/ElementsProject/lightning/pull/7969
[#7921]: https://github.com/ElementsProject/lightning/pull/7921
[#8089]: https://github.com/ElementsProject/lightning/pull/8089
[#8052]: https://github.com/ElementsProject/lightning/pull/8052
[#8019]: https://github.com/ElementsProject/lightning/pull/8019
[#7958]: https://github.com/ElementsProject/lightning/pull/7958
[#8027]: https://github.com/ElementsProject/lightning/pull/8027
[#7173]: https://github.com/ElementsProject/lightning/pull/7173
[#7937]: https://github.com/ElementsProject/lightning/pull/7937
[#8056]: https://github.com/ElementsProject/lightning/pull/8056
[#8037]: https://github.com/ElementsProject/lightning/pull/8037
[#8077]: https://github.com/ElementsProject/lightning/pull/8077
[#7887]: https://github.com/ElementsProject/lightning/pull/7887
[#7907]: https://github.com/ElementsProject/lightning/pull/7907
[#7979]: https://github.com/ElementsProject/lightning/pull/7979
[#8053]: https://github.com/ElementsProject/lightning/pull/8053
[#7908]: https://github.com/ElementsProject/lightning/pull/7908
[#7894]: https://github.com/ElementsProject/lightning/pull/7894
[#7924]: https://github.com/ElementsProject/lightning/pull/7924
[#8057]: https://github.com/ElementsProject/lightning/pull/8057
[#8031]: https://github.com/ElementsProject/lightning/pull/8031
[#8010]: https://github.com/ElementsProject/lightning/pull/8010
[#8071]: https://github.com/ElementsProject/lightning/pull/8071
[#7933]: https://github.com/ElementsProject/lightning/pull/7933
[#7508]: https://github.com/ElementsProject/lightning/pull/7508
[#8084]: https://github.com/ElementsProject/lightning/pull/8084
[#8085]: https://github.com/ElementsProject/lightning/pull/8085
[#8095]: https://github.com/ElementsProject/lightning/pull/8095
[#7941]: https://github.com/ElementsProject/lightning/pull/7941
[#8059]: https://github.com/ElementsProject/lightning/pull/8059
[#8069]: https://github.com/ElementsProject/lightning/pull/8069
[#8022]: https://github.com/ElementsProject/lightning/pull/8022
[#7938]: https://github.com/ElementsProject/lightning/pull/7938
[#7509]: https://github.com/ElementsProject/lightning/pull/7509
[#8094]: https://github.com/ElementsProject/lightning/pull/8094
[#8104]: https://github.com/ElementsProject/lightning/pull/8104
[#7935]: https://github.com/ElementsProject/lightning/pull/7935
[#7942]: https://github.com/ElementsProject/lightning/pull/7942
[#7772]: https://github.com/ElementsProject/lightning/pull/7772
[#8060]: https://github.com/ElementsProject/lightning/pull/8060
[25.02]: https://github.com/ElementsProject/lightning/releases/tag/v25.02
## [24.11.1] - 2024-12-16: "The lightning-dev Mailing List II"
Minor fixes, particularly for xpay users.
### Changed
- JSON-RPC: `xpay` now gives the same JSON success return as documented by `pay` when `xpay-handle-pay` is set. ([#7938], [#7952])
- JSON-RPC: With `xpay-handle-pay` set, xpay will now be used even if `pay` uses maxfeeprecent or exemptfee parameters (e.g. Zeus) ([#7942])
- JSON-RPC: `xpay` now populates more fields, so `listsendpays` and `listpays` show `destination` and `amount_msat` fields for xpay payments. ([#7941])
- Logging: we no longer suppress DEBUG messages from subdaemons. ([#7935])
### Fixed
- JSON-RPC: xpay now works through unannounced channels. ([#7937])
- lightning-cli: fix "malformed response" bug ([#7924])
- Plugins: `xpay` no longer logs "Got command" at info level. ([#7933])
- Build: Alpine/OpenBSD compilation fix ([#7940])
[#7942]: https://github.com/ElementsProject/lightning/pull/7942
[#7933]: https://github.com/ElementsProject/lightning/pull/7933
[#7941]: https://github.com/ElementsProject/lightning/pull/7941
[#7937]: https://github.com/ElementsProject/lightning/pull/7937
[#7924]: https://github.com/ElementsProject/lightning/pull/7924
[#7935]: https://github.com/ElementsProject/lightning/pull/7935
[#7938]: https://github.com/ElementsProject/lightning/pull/7938
[#7940]: https://github.com/ElementsProject/lightning/pull/7940
[#7952]: https://github.com/ElementsProject/lightning/pull/7952
[24.11.1]: https://github.com/ElementsProject/lightning/releases/tag/v24.11.1
## [24.11] - 2024-12-09: "The lightning-dev Mailing List"
This release named by Dusty Daemon.
### Added
- JSON-RPC: `listaddresses` to list issued addresses from the node. ([#7800])
- Config: `autoconnect-seeker-peers`, allowing seeker to reach out to new nodes for additional gossip (default: 10). ([#7798])
- Protocol: `option_quiesce` enabled by default. ([#7586])
- JSON-RPC: `fetchinvoice` allows setting invreq_metadata via `payer_metadata` parameter. ([#7786])
- hsmtool: generatehsm can run non-interactive, taking options on the cmdline. ([#7102])
- Plugins: `pay` now has tracing support for various payment steps. ([#7803])
- Plugins: new notification `onionmessage_forward_fail`.
- JSON-RPC: `exposesecret` command for encouraging hsm_secret backups. ([#7647])
- JSON-RPC: `listpays` has `index`, `start` and `limit` parameters for listing control. ([#7385])
- Plugins: bookkeeper has a new RPC `bkpr-editdescriptionbypaymentid` which will update the description for any event with matching payment_id ([#7604])
- Config: `grpc-host` option for grpc plugin ([#7479])
- JSON-RPC: A new magic `dev-splice` command is added that can take a splice script or json payload and perform any complex splice across multiple channels merging the result into a single transaction. Some features are disabled and will be added in time. ([#6980])
- JSON-RPC: low-level RPC command `addpsbtinput` to fund PSBTs directly and help with complex splices & dual-opens. ([#6980])
- JSON-RPC: `stfu_channels` and `abort_channels` are added for bulk multi-channel splice commands. These allow the user to pause (and resume) multiple channels in place. ([#6980])
- JSON-RPC: `injectpaymentonion` for initiating an HTLC like a peer would do. ([#7749])
- Documentation: Example documentation on generating custom gRPC ([#7731])
- Installation: Nix users can now install CLN from the new flake. ([#7656])
- JSON-RPC: `decode` now used modern BOLT 4 language for blinded paths, `first_path_key`. ([#7586])
- Plugins: `onion_message_recv` and `onion_message_recv_secret` hooks now used modern BOLT 4 language for blinded paths, `first_path_key`. ([#7586])
- JSON-RPC: keysend `maxfee` parameter for consistency with pay. ([#7227]) ([#7653])
- `hsmtool`: `getnodeid` command derives the node id from the hsm_secret, to verify it's the correct secret. ([#7644])
### Changed
- Plugins: grpc now starts on port 9736 by default (localhost, see `grpc-host`) ([#7479])
- Config: bolt12 now enabled by default (finally!) ([#7833])
- Protocol: we now connect to additional nodes for improved gossip (see `autoconnect-seeker-peers`) ([#7798])
- Protocol: Own-channel gossip is broadcast to more peers (up to 50, not 5). ([#7873])
- Build: Added architecture identifier to Ubuntu release ([#7797])
- Logging: connectd now logs unknown messages as "UNKNOWN" not "INVALID" to avoid freaking people out. ([#7892])
- Protocol: we now create a low-priority (2016 down to 12 blocks fee target) anchor for low-fee unilateral closes even if there's no urgency. ([#7832])
- Protocol: splicing moved from test numbers to spec numbers. ([#7719])
- Protocol: Support added for peers that wish to rotate their funding pubkey during a splice. ([#7719])
- Startup: reconnecting to peers at startup should be significantly faster (dependent on machine speed). ([#7630])
- Protocol: we remember the last successful address we connected to for important peers. ([#7630])
- Protocol: Gossipd requests a full sync from a random peer every hour. ([#7768])
- JSON-RPC: `injectonionmessage` API simplified and documented.
- JSON-RPC: Improved error messaging for splice commands. ([#7719])
- JSON-RPC: built-in plugins can now be stopped using "plugin stop". ([#7799])
- Wallet: Taproot addresses are used for unilateral-close change addresses. ([#7800])
- JSON-RPC: `close` now outputs txs & txids of all closing transactions (splice candidates can cause there to be multiple). ([#7466])
- JSON-RPC: `splice_update` can in some cases now return the remotely partiall signed psbt to the user, if so `signtures_secured` will be true. ([#6980])
- JSON-RPC: `splice_signed` parameters are switched in order to make `channel_id` an optional parameter, enabling multi-splice-signatures. ([#6980])
- `pay`: Discarding an overly long or expensive route does not blocklist channels anymore. ([#7494])
- Plugins: `cln-grpc` Upgrade tonic version and ([#7598])
### Deprecated
Note: You should always set `allow-deprecated-apis=false` to test for changes.
- Config: `experimental-offers` (it's now the default). ([#7833])
- Config: `experimental-quiesce`: it's now the default. ([#7586])
- JSON-RPC: `close` `tx` and `txid` field (use `txs` and `txids`) ([#7466])
- JSON-RPC: `decodepay`: use `decode`. ([#7551])
- JSON-RPC: `decode` `blinding` in blinded path: use `first_path_key`. ([#7586])
- JSON-RPC: `onion_message_recv` and `onion_message_recv_secret` hooks `blinding` in blinded path: use `first_path_key`. ([#7586])
### Fixed
- JSON-RPC: `decode` refused to decode expired bolt12 invoices. ([#7890])
- JSON-RPC: `listforwards` `received-time` is always present (it could be missing for ancient nodes, now it will be 0) ([#7744])
- Plugins: `cln-grpc` now understands channel type `anchors/even` ([#7628])
- Plugins: `cln-grpc` no longer logs a warning if a notification does not have a handler ([#7867])
- JSON-RPC: `close` now correctly reports the txid of the remote onchain unilateral tx if it races with a peer close. ([#7593])
- Protocol: we no longer try to spend anchors if a commitment tx is already mined (reported by @niftynei). ([#7593])
- pyln-client: plugins now compatible with CLN <= 24.05 (broken in 24.08) ([#7852])
- Protocol: Receiving bolt12 payments where we have no public channels would fail a few blocks after startup. ([#7839])
- Protocol: entry to blinded paths returns more useful errors (e.g if it's the final node, you get a real error, otherwise you get invalid_onion_blinding). ([#7839])
- build: fix overzealous warning from clang 19. ([#7829])
- `gossipd` will no longer miss some channel closes on restart. ([#7343])
- `onchaind` can miss conclusion of final txs in some cases, will now replay independently. ([#7343])
- Plugins: `autoclean` is now gentler on the node when doing giant cleans. ([#7805])
- Plugins: libplugin plugins can now intercept `rpc_command` hook without deadlocking. ([#7750])
- Plugins: `pay`: debug logging now uses correct JSON ids. ([#7750])
- Tools: Fixed regtest directory location for giantnode script. ([#7791])
- JSON-RPC: `fetchinvoice` typo fixed about parameters name in err str ([#7787])
- Performance: `connectd` and `gossipd` message queues are much more efficient. ([#7767])
- Documentation: version strings in documentation should now be correvt ([#7694])
- Protocol: we could get confused on restart and not re-transmit our own channel_updates. ([#7737])
- connectd: crash on erroneous timeout. ([#7736])
- Performance: `pay` now only calls listpeerchannels once ([#7705])
- gossipd: crash errors with large gossip_store (>4MB) growth on longer-running nodes. ([#7729])
- Performance: `pay` pathfinding speedups for large nodes. ([#7726])
- Performance: `listchannels` performance improved on large nodes if deprecated options disabled (omitting call to `listpeerchannels`) ([#7704])
- pyln-testing: Fix file descriptor leak in bitcoind fixture. ([#7130]) ([#7669])
- JSON-RPC: `listpeerchannels` (and thus, pay) sped up on very large nodes. ([#7679])
- lightningd: no longer crash if a plugin dies during lightningd startup. ([#7673])
- cln-plugin: Change default log level filter back to INFO ([#7668])
- Logging: removed bogus "**BROKEN** plugin-topology: DEPRECATED API USED: listchannels.include_private" message. ([#7663])
- Logging: When DEBUG printing first tx depth, we printed the wrong value ([#7910])
- Documentation: schemas: Make description in `Wait(any)invoiceResponse` optional to handle BOLT12 ([#7667])
- Fixed intermittant bug where hsmd (particularly, but also lightningd) could use 100% CPU. ([#7661])
- Docker image created via github actions correctly reads the tag available on the HEAD. ([#7625])
- Build: Core lightning's version will not be suffixed with -modded anymore. ([#7625])
### EXPERIMENTAL
- Plugins: `cln-xpay`, with associated `xpay` command for payments (plans to replace `pay` in future). ([#7799])
- Config: option `xpay-handle-pay` can be used to call xpay when pay is used in many cases (but output is different from pay!) ([#7799])
- Plugins: `askrene` which provides `getroutes` and a complete API for adding information in layers. ([#7782])
[#7694]: https://github.com/ElementsProject/lightning/pull/7694
[#7644]: https://github.com/ElementsProject/lightning/pull/7644
[#7803]: https://github.com/ElementsProject/lightning/pull/7803
[#7782]: https://github.com/ElementsProject/lightning/pull/7782
[#7479]: https://github.com/ElementsProject/lightning/pull/7479
[#7705]: https://github.com/ElementsProject/lightning/pull/7705
[#7839]: https://github.com/ElementsProject/lightning/pull/7839
[#7551]: https://github.com/ElementsProject/lightning/pull/7551
[#7798]: https://github.com/ElementsProject/lightning/pull/7798
[#7647]: https://github.com/ElementsProject/lightning/pull/7647
[#7744]: https://github.com/ElementsProject/lightning/pull/7744
[#7832]: https://github.com/ElementsProject/lightning/pull/7832
[#7767]: https://github.com/ElementsProject/lightning/pull/7767
[#7768]: https://github.com/ElementsProject/lightning/pull/7768
[#7656]: https://github.com/ElementsProject/lightning/pull/7656
[#7604]: https://github.com/ElementsProject/lightning/pull/7604
[#7707]: https://github.com/ElementsProject/lightning/pull/7707
[#7750]: https://github.com/ElementsProject/lightning/pull/7750
[#7628]: https://github.com/ElementsProject/lightning/pull/7628
[#7343]: https://github.com/ElementsProject/lightning/pull/7343
[#7102]: https://github.com/ElementsProject/lightning/pull/7102
[#7731]: https://github.com/ElementsProject/lightning/pull/7731
[#7679]: https://github.com/ElementsProject/lightning/pull/7679
[#7673]: https://github.com/ElementsProject/lightning/pull/7673
[#7749]: https://github.com/ElementsProject/lightning/pull/7749
[#7668]: https://github.com/ElementsProject/lightning/pull/7668
[#7494]: https://github.com/ElementsProject/lightning/pull/7494
[#7786]: https://github.com/ElementsProject/lightning/pull/7786
[#7466]: https://github.com/ElementsProject/lightning/pull/7466
[#7787]: https://github.com/ElementsProject/lightning/pull/7787
[#7625]: https://github.com/ElementsProject/lightning/pull/7625
[#7800]: https://github.com/ElementsProject/lightning/pull/7800
[#7829]: https://github.com/ElementsProject/lightning/pull/7829
[#6980]: https://github.com/ElementsProject/lightning/pull/6980
[#7653]: https://github.com/ElementsProject/lightning/pull/7653
[#7734]: https://github.com/ElementsProject/lightning/pull/7734
[#7867]: https://github.com/ElementsProject/lightning/pull/7867
[#7630]: https://github.com/ElementsProject/lightning/pull/7630
[#7667]: https://github.com/ElementsProject/lightning/pull/7667
[#7799]: https://github.com/ElementsProject/lightning/pull/7799
[#7736]: https://github.com/ElementsProject/lightning/pull/7736
[#7719]: https://github.com/ElementsProject/lightning/pull/7719
[#7593]: https://github.com/ElementsProject/lightning/pull/7593
[#7833]: https://github.com/ElementsProject/lightning/pull/7833
[#7770]: https://github.com/ElementsProject/lightning/pull/7770
[#7737]: https://github.com/ElementsProject/lightning/pull/7737
[#7586]: https://github.com/ElementsProject/lightning/pull/7586
[#7726]: https://github.com/ElementsProject/lightning/pull/7726
[#7805]: https://github.com/ElementsProject/lightning/pull/7805
[#7598]: https://github.com/ElementsProject/lightning/pull/7598
[#7791]: https://github.com/ElementsProject/lightning/pull/7791
[#7385]: https://github.com/ElementsProject/lightning/pull/7385
[#7669]: https://github.com/ElementsProject/lightning/pull/7669
[#7663]: https://github.com/ElementsProject/lightning/pull/7663
[#7661]: https://github.com/ElementsProject/lightning/pull/7661
[#7729]: https://github.com/ElementsProject/lightning/pull/7729
[#7852]: https://github.com/ElementsProject/lightning/pull/7852
[#7740]: https://github.com/ElementsProject/lightning/pull/7740
[#7704]: https://github.com/ElementsProject/lightning/pull/7704
[#7756]: https://github.com/ElementsProject/lightning/pull/7756
[#7873]: https://github.com/ElementsProject/lightning/pull/7873
[#7890]: https://github.com/ElementsProject/lightning/pull/7890
[#7797]: https://github.com/ElementsProject/lightning/pull/7797
[#7892]: https://github.com/ElementsProject/lightning/pull/7892
[#7910]: https://github.com/ElementsProject/lightning/pull/7910
[24.11]: https://github.com/ElementsProject/lightning/releases/tag/v24.11
## [24.08.2] - 2024-10-18: "Steel Backed-up Channels"
This point release addresses few crash fixes and includes an enhancement to remember and update channel hints for payments.
### Changed
- pay: Now remembers and updates channel hints across payments ([#7494])
- pay: Discarding an overly long or expensive route does not blacklist channels anymore. ([#7494])
- grpc: Channel type `anchors/even` was added to the grpc bindings. ([#7628])
### Fixed
- gossipd: crash errors with large gossip_store (>4MB) growth on longer-running nodes. ([#7729])
- connectd: crash on erroneous timeout. ([#7736])
- Protocol: we could get confused on restart and not re-transmit our own channel_updates. ([#7737])
- rpc: `listpeerchannels` (and thus, pay) sped up on very large nodes. ([#7679])
- Improved pathfinding speed for large nodes. ([#7726])
[#7494]: https://github.com/ElementsProject/lightning/pull/7494
[#7628]: https://github.com/ElementsProject/lightning/pull/7628
[#7679]: https://github.com/ElementsProject/lightning/pull/7679
[#7726]: https://github.com/ElementsProject/lightning/pull/7726
[#7729]: https://github.com/ElementsProject/lightning/pull/7729
[#7736]: https://github.com/ElementsProject/lightning/pull/7736
[#7737]: https://github.com/ElementsProject/lightning/pull/7737
[24.08.2]: https://github.com/ElementsProject/lightning/releases/tag/v24.08.2
## [24.08.1] - 2024-09-16: "Steel Backed-up Channels"
This hotfix release fixes few crash issues and some other bugs.
### Fixed
- No longer crash if a plugin dies during lightningd startup. ([#7673])
- Fixed crash when starting channeld for older channel with no local alias. ([#7664])
- Will not crash for older pre-tlv peers where send_tlvs is NULL. ([#7650])
- Compilation will fail gracefully if `jq` is missing or an outdated version is detected. ([#7662])
- cln-plugin: Change default log level filter back to INFO ([#7668])
- Fixed intermittant bug where hsmd (particularly, but also lightningd) could use 100% CPU. ([#7661])
- Made `description` optional in `Wait(any)invoiceResponse` to handle BOLT12 ([#7667])
- Removed bogus "**BROKEN** plugin-topology: DEPRECATED API USED: listchannels.include_private" message. ([#7663])
[#7673]: https://github.com/ElementsProject/lightning/pull/7673
[#7668]: https://github.com/ElementsProject/lightning/pull/7668
[#7667]: https://github.com/ElementsProject/lightning/pull/7667
[#7664]: https://github.com/ElementsProject/lightning/pull/7664
[#7663]: https://github.com/ElementsProject/lightning/pull/7663
[#7662]: https://github.com/ElementsProject/lightning/pull/7662
[#7661]: https://github.com/ElementsProject/lightning/pull/7661
[#7650]: https://github.com/ElementsProject/lightning/pull/7650
## [24.08] - 2024-08-28: "Steel Backed-up Channels"
This release named by @Lagrang3.
### Added
- protocol: onion messages are now supported by default. ([#7455])
- protocol: onion messages can now be forwarded by short_channel_id. ([#7455])
- pay: The pay plugin now checks whether we have enough spendable capacity before computing a route, returning a clear error message if we don't ([#7418])
- pay: Payments now emit `channel_hint_updated` notification to share inferred balances and observations across multiple payments. ([#7487])
- pay: The pay plugin now returns better error codes ([#7418])
- reckless-rpc plugin: issue commands to reckless over rpc. ([#7506])
- reckless: accepts json array input for command targets ([#7484])
- reckless provides json output with option flag -j/--json ([#7484])
- reckless: added the ability to install rust plugins. ([#7484])
- JSON-RPC: `listpeers` `features` array string uses "option_anchors" for feature 22/23, following renaming in BOLT 9. ([#7388])
- plugins: `bookkeeper` now listens for two custom events: `utxo_deposit` and `utxo_spend`. This allows for 3rd party plugins to send onchain coin events to the `bookkeeper`. See the new plugins/bkpr/README.md for details on how these work! ([#7258])
- plugins: Add payment_id parameter to bkpr-listaccountevents to filter events. ([#7536])
- cln-plugin: add multi options for String and i64 ([#7544])
- pyln-client: Added a notification mechanism for config changes ([#7289])
- pyln-client: implement setconfig hook for plugins so you can see changes in `dynamic` options. ([#7289])
- doc: all examples in the documentation are now generated from running the code, so they are current. ([#7457])
### Changed
- protocol: We now send current peers our changed gossip (even if they set timestamp_filter otherwise), not just on reconnect. ([#7554])
- protocol: we now always ask the first peer for all its gossip. ([#7512])
- connectd: I/O optimizations to significantly speed up larger nodes. ([#7365])
- plugins: the `fetchinvoice` plugin has been combined into the `offers` plugin. ([#7456])
- close: We no longer attempt to publish a unilateral close that'd fail anyway when we witness a close onchain. ([#7447])
- pay: Improved logging should facilitate debugging considerably. ([#7418])
- reckless: option flags are now position independent. ([#7484])
- plugins: now allows date and time sqlite functions. ([#7467])
- splice: added outnum of new funding output to splice_signed RPC command ([#7465])
- lightningd: we wait for bitcoind if it has somehow gone backwards (as long as header height is still ok). ([#7342])
- wallet: The channel status is printed when loading it from the DB ([#7354])
- JSON-RPC: `listclosedchannels`, `listpeerchannels`, `openchannel_update`, `openchannel_init`, `fundchannel`, `fundchannel_start` and `multifundchannel`: `channel_type` array `names` now contains "anchors" instead of "anchors_zero_fee_htlc_tx". ([#7388])
- JSON-RPC: Do not return the contents of invalid parameters in error messages, refer to logs (use 'check' to get full error messages) ([#7420])
- lightningd: `--list-features-only` now lists "option_anchors" instead of "option_anchors_zero_fee_htlc_tx". ([#7388])
- updated Bitcoin to v27.1 and Elements to v23.2.1 ([#7436])
- update libwally to 1.3.0 ([#7480])
### Deprecated
Note: You should always set `allow-deprecated-apis=false` to test for changes.
- JSON-RPC: `listpeers` `features` array string "option_anchors_zero_fee_htlc_tx": use "option_anchors" (spec renamed it). ([#7388])
- config: the --experimental-onion-messages option is ignored (on by default). ([#7455])
- config: the --experimental-anchors option is ignored (on by default since v24.02). ([#7454])
- pyln-client: `category`, `description` and `long_description` for RPC commands are deprecated now. ([#7520])
### Removed
- JSON-RPC: `sendonionmessage` (was experimental only, use `injectonionmessage`) ([#7461])
- JSON-RPC: `autocleaninvoice` command (deprecated v22.11, EOL v24.02) ([#7298])
- plugins: `estimatefees` returning feerates by name (e.g. "opening"); deprecated in v23.05. ([#7380])
### Fixed
- protocol: we can now open unannounced channels with LND nodes again. ([#7564])
- plugins: `sql` crash on querying `listpeerchannels` during channel establishment. ([#7578])
- config: whitespace at the end of (most) options is now ignored, not complained about. ([#7251])
- connectd: now should use far less CPU on large nodes. ([#7365])
- lightningd: occasionally we could miss transaction outputs (not telling gossipd, or even onchaind) ([#7567])
- notifications: we now send a `coin_movement` notification for splice confirmations of channel funding outpoint spends. ([#7533])
### EXPERIMENTAL
- JSON-RPC: `offer` removed `@` prefix support from `recurrence_base` (use `recurrence_start_any_period` set to `false`) ([#7380])
- protocol: pay can now pay to bolt12 invoices if entry to blinded hop is specified as a short_channel_id (rather than node id). ([#7461])
- plugins: pay can now pay a bolt12 invoice even if we, ourselves, are the head of the blinded path within it. ([#7461])
- offers: automatically add a blinded path from a peer if we have no public channels, so unannounced nodes can have offers too. ([#7461])
- offers: we can now self-fetch and self-pay BOLT12 offers and invoices. ([#7461])
- offers: recurring offers had incompatible changes, won't work against older versions. ([#7476])
- offers: handle experimental ranges in offers/invoice_requests/invoices. ([#7474])
- offers: `invoicerequest` will set a blinded path if we're an unannounced node. ([#7476])
- offers: `sendinvoice` will use a blinded path in an invoice_request, if specified. ([#7476])
- offers: maintain unknown fields offers/invoice_requests correctly. ([#7474])
- offers: fixed: onionmessage replies now work even if we need to route to the start of the blinded reply path. ([#7456])
- offers: fixed: fetchinvoice tries all blinded paths until one is usable, and handles case where we have to route more than one hop to reach the entry point. ([#7456])
- renepay: prune the network by disabling channels we don't like, eg. very low max_htlc. ([#7403])
- renepay: fixed: un-reserve routes that have completed or failed ([#7357])
- renepay: Add a dev parameter representing a constant probability of availability for all channels in the network. ([#7540])
- renepay: add cli option "exclude" to manually disable channels and nodes. ([#7403])
[#7540]: https://github.com/ElementsProject/lightning/pull/7540
[#7578]: https://github.com/ElementsProject/lightning/pull/7578
[#7447]: https://github.com/ElementsProject/lightning/pull/7447
[#7420]: https://github.com/ElementsProject/lightning/pull/7420
[#7418]: https://github.com/ElementsProject/lightning/pull/7418
[#7454]: https://github.com/ElementsProject/lightning/pull/7454
[#7436]: https://github.com/ElementsProject/lightning/pull/7436
[#7484]: https://github.com/ElementsProject/lightning/pull/7484
[#7544]: https://github.com/ElementsProject/lightning/pull/7544
[#7476]: https://github.com/ElementsProject/lightning/pull/7476
[#7456]: https://github.com/ElementsProject/lightning/pull/7456
[#7403]: https://github.com/ElementsProject/lightning/pull/7403
[#7289]: https://github.com/ElementsProject/lightning/pull/7289
[#7388]: https://github.com/ElementsProject/lightning/pull/7388
[#7474]: https://github.com/ElementsProject/lightning/pull/7474
[#7536]: https://github.com/ElementsProject/lightning/pull/7536
[#7457]: https://github.com/ElementsProject/lightning/pull/7457
[#7467]: https://github.com/ElementsProject/lightning/pull/7467
[#7487]: https://github.com/ElementsProject/lightning/pull/7487
[#7251]: https://github.com/ElementsProject/lightning/pull/7251
[#7365]: https://github.com/ElementsProject/lightning/pull/7365
[#7461]: https://github.com/ElementsProject/lightning/pull/7461
[#7520]: https://github.com/ElementsProject/lightning/pull/7520
[#7357]: https://github.com/ElementsProject/lightning/pull/7357
[#7480]: https://github.com/ElementsProject/lightning/pull/7480
[#7465]: https://github.com/ElementsProject/lightning/pull/7465
[#7354]: https://github.com/ElementsProject/lightning/pull/7354
[#7512]: https://github.com/ElementsProject/lightning/pull/7512
[#7380]: https://github.com/ElementsProject/lightning/pull/7380
[#7564]: https://github.com/ElementsProject/lightning/pull/7564
[#7455]: https://github.com/ElementsProject/lightning/pull/7455
[#7342]: https://github.com/ElementsProject/lightning/pull/7342
[#7506]: https://github.com/ElementsProject/lightning/pull/7506
[#7554]: https://github.com/ElementsProject/lightning/pull/7554
[#7258]: https://github.com/ElementsProject/lightning/pull/7258
[#7533]: https://github.com/ElementsProject/lightning/pull/7533
[#7567]: https://github.com/ElementsProject/lightning/pull/7567
[#7298]: https://github.com/ElementsProject/lightning/pull/7298
[24.08]: https://github.com/ElementsProject/lightning/releases/tag/v24.08
## [24.05] - 2024-06-04: "The Infinitely Divisible Satoshi"
This release named by @daywalker90.
### Added
- JSON-RPC: `createrune` new restriction `pinv` to examine bolt11/bolt12 invoice fields (e.g. amount of invoice). ([#7165])
- Plugins: `cln-plugin` adds dynamic configs and a callback for changes ([#7293])
- JSON-RPC: `pay` has a new parameter `partial_msat` to only pay part of an invoice (someone else presumably will pay the rest at the same time!) ([#7145])
- JSON-RPC: `check` `keysend` now checks with HSM that it will approve it. ([#7111])
- Plugins: Can now opt in to handle `check` command on their commands, for more thorough checking. ([#7111])
- JSON-RPC: `check` `setconfig` now checks that the new config setting would be valid. ([#7111])
- JSON-RPC: `check` `setconfig` on plugin options can now check the config value would be accepted. ([#7111])
- Plugins: `cln-grpc` adds notifications over the grpc interface. Configurable with config parameter `grpc-msg-buffer-size`. ([#7084])
- Plugins: Added `wss-proxy`, a WSS Proxy server with `wss-bind-addr` and `wss-certs` configurations. ([#7225])
- Plugins: `cln-grpc` added GRPC support for remaining methods: `dev-forget-channel`, `emergencyrecover`, `recover`, `recoverchannel`, `funderupdate`, `help`, `invoicerequest`, `listinvoicerequests`, `disableinvoicerequest`, `listconfigs`, `makesecret`, `multiwithdraw`, `showrunes`, `createrune`, `blacklistrune`, `checkrune` ([#7317]), addpsbtoutput ([#7108]), `openchannel_init`, `openchannel_abort`, `openchannel_bump`, `openchannel_signed`, `openchannel_update` ([#7230]), `delpay` ([#7232]), `delforward` ([#7260]), `autoclean-once`, `autoclean-status` ([#7238]), `fundchannel_start`, `fundchannel_complete`, `fundchannel_cancel` ([#7231]), `bkpr-channelsapy`, `bkpr-dumpincomecsv`, `bkpr-inspect`, `bkpr-listaccountevents`, `bkpr-listbalances` ([#7256]), `disableoffer` ([#7233]), `parsefeerate`, `plugin`, `renepay`, `renepaystatus`, `sendinvoice` ([#7272]), `reserveinputs`, `unreserveinputs`, `splice_init`, `splice_signed`, `splice_update` ([#7273]), `sendonionmessage`, `setconfig`, `setpsbtversion`, `upgradewallet` ([#7274]).
- Plugins: `cln_plugin` adds rust plugin support for wildcard `*` subscriptions. ([#7106])
- Config: Add `bitcoin-rpcclienttimeout` config parameter. ([#7095])
- Plugins: new `log` notification when a log line is emitted. ([#6990])
- Config: new log level `trace` where we moved the very noisiest `debug` logs. ([#7280])
- Plugins: `clnrest` added a new configuration `clnrest-swagger-root` to change the default Swagger UI path from `/` to custom url. ([#7256])
### Changed
- Documentation: great documentation rewrite, all reference pages now generated from the fully-tested JSON schemas and include examples. ([#6995])
- Protocol: `--ignore-fee-limits` / `setchannel ignorefeelimits` no longer applies to mutual close. ([#7252])
- Plugins: `bcli`: Add a path that tries to fetch blocks ([#7240])
- Plugins: libplugin now shows plugin option default values (where they're non-trivial) ([#7306])
- Runes: named parameters (e.g. `pnameamountmsat`) no longer need to remove underscores (i.e. `pnameamount_msat` now works as expected). ([#7124])
- lightningd: we now try to increase the number of file descriptors, if it's less than twice the number of channels at startup (and log if we cannot!). ([#7237])
- connectd: prioritize peers with channels (and log!) if we run low on file descriptors. ([#7237])
- lightningd: Processing blocks should now be faster ([#7101])
- Plugins: `cln-grpc` adds routes to `decode` and `decodepay` results ([#7317])
- hsmd: the hsmd now supports `HSM_VERSION 6` ([#7178])
- hsmd: `HSM_VERSION 6`: `get_per_commitment_point` does not imply index - 2 is revoked, makes it safe to call on any index. ([#7178])
- Documentation: Merged `example_json_request` and `example_json_response` in a single `json_examples` array to maintain the request and its corresponding response together. ([#7181])
- JSON-RPC: `stop` and `recover` now return a JSON object (not a raw string!) like every other command does. ([#6995])
- Plugins: `pay` payments are more robust for nodes that are currently syncing. ([#7190])
### Deprecated
Note: You should always set `allow-deprecated-apis=false` to test for changes.
### Removed
- Plugins: no longer allow missing `id` field in commando requests (deprecated v23.02, EOL v24.02) ([#7094])
- JSON-RPC: `createrune` restrictions as raw strings (use arrays) (deprecated v23.05, EOL 24.02). ([#7094])
- JSON-RPC: `listpeers` `channels` (deprecated v23.02, EOL v24.02) ([#7094])
- JSON-RPC: `sendpay` ignoring first channel (deprecated v0.12, EOL v24.02) ([#7094])
- Config: `experimental-websocket-port` (deprecated 23.08, EOL 24.02) ([#7094])
- Plugins: `funding_locked` from `channel_opened` notification (deprecated v22.11, EOL v24.02) ([#7094])
- JSON-RPC: `feerates` output fields `delayed_to_us` and `htlc_resolution`. ([#7094])
- Config: `autocleaninvoice-cycle` and `autocleaninvoice-expired-by` (deprecated v22.11, EOL v24.02) ([#7094])
- JSON-RPC: `delexpiredinvoice` (deprecated v22.11, EOL v24.02) ([#7094])
- JSON-RPC feerates by internal names ("opening", "mutual_close", "delayed_to_us", "htlc_resolution", "penalty", "min_acceptable", "max_acceptable") (deprecated v23.05, EOL v24.02). ([#7094])
- Plugins: `invoice_payment` and `htlc_accepted` hook `failure_code` response (deprecated v22.08 and v0.8, EOL v23.02) ([#7094])
### Fixed
- Plugins: `pay` now correctly estimates channel capacity ([#7188])
- lightningd: avoid crash on signing failure when trying to spend anchor outputs. ([#7291])
- Plugins: `renepay` fixed a race condition leading to a crash. ([#7125])
- JSON-RPC: `fundchannel_start` now disallows a non-zero `mindepth` parameter if you ask for a zeroconf `channel_type`. ([#7175])
- pyln-client: Fix Plugin.notify_message() not to ignore `level` parameter. ([#7287])
- JSON-RPC: `multifundchannel` with `all` as an amount works as expected. ([#7037])
- Plugins: `pay` crash fixed, caused by parsing uncommitted dual open channels ([#7235])
- Plugins: `clnrest` now correctly self-disables if Python not present at all. ([#7211])
- lightningd: slow memory leak when using plugin hooks fixed (introduced in v23.11) ([#7192])
- Plugins: `recovery` is less noisy. ([#7116])
- Plugins: `renepay` handles htlc_max correctly for local channels. ([#7159])
- Plugins: The recover plugin now avoids trying to recover closed channels. ([#7216])
- Gossmap: Avoid adding redundant channel announcements to the gossip_store. ([#7330])
- Protocol: forward legacy non-TLV onions which we removed in 22.11 and spec itself in Feb 2022. Still sent by LND nodes who haven't seen our node_announcement. ([#7352])
- Protocol: we once again send CHANNEL_REESTABLISH responses on closing channels. ([#7353])
- gossipd: Fixed a crash when processing pending node announcements. ([#7368])
### EXPERIMENTAL
- offers: We will now reply to invoice_request messages even if reply path requires us to make an outgoing connection (LDK does this) ([#7304])
- offers: we now understand blinded paths which use a short-channel-id(+direction) as entry point. ([#7212])
- offers: Fix blinded paths in invoices - use node_id and set final node's CLTV delta. ([#7311])
[#7368]: https://github.com/ElementsProject/lightning/pull/7368
[#7353]: https://github.com/ElementsProject/lightning/pull/7353
[#7352]: https://github.com/ElementsProject/lightning/pull/7352
[#7159]: https://github.com/ElementsProject/lightning/pull/7159
[#7116]: https://github.com/ElementsProject/lightning/pull/7116
[#7230]: https://github.com/ElementsProject/lightning/pull/7230
[#7232]: https://github.com/ElementsProject/lightning/pull/7232
[#7260]: https://github.com/ElementsProject/lightning/pull/7260
[#7238]: https://github.com/ElementsProject/lightning/pull/7238
[#7231]: https://github.com/ElementsProject/lightning/pull/7231
[#7256]: https://github.com/ElementsProject/lightning/pull/7256
[#7233]: https://github.com/ElementsProject/lightning/pull/7233
[#7190]: https://github.com/ElementsProject/lightning/pull/7190
[#7095]: https://github.com/ElementsProject/lightning/pull/7095
[#7272]: https://github.com/ElementsProject/lightning/pull/7272
[#7273]: https://github.com/ElementsProject/lightning/pull/7273
[#7311]: https://github.com/ElementsProject/lightning/pull/7311
[#7274]: https://github.com/ElementsProject/lightning/pull/7274
[#7330]: https://github.com/ElementsProject/lightning/pull/7330
[#7181]: https://github.com/ElementsProject/lightning/pull/7181
[#7124]: https://github.com/ElementsProject/lightning/pull/7124
[#7287]: https://github.com/ElementsProject/lightning/pull/7287
[#6995]: https://github.com/ElementsProject/lightning/pull/6995
[#7225]: https://github.com/ElementsProject/lightning/pull/7225
[#7317]: https://github.com/ElementsProject/lightning/pull/7317
[#7108]: https://github.com/ElementsProject/lightning/pull/7108
[#7111]: https://github.com/ElementsProject/lightning/pull/7111
[#7240]: https://github.com/ElementsProject/lightning/pull/7240
[#7165]: https://github.com/ElementsProject/lightning/pull/7165
[#7175]: https://github.com/ElementsProject/lightning/pull/7175
[#7212]: https://github.com/ElementsProject/lightning/pull/7212
[#7252]: https://github.com/ElementsProject/lightning/pull/7252
[#7094]: https://github.com/ElementsProject/lightning/pull/7094
[#7145]: https://github.com/ElementsProject/lightning/pull/7145
[#7101]: https://github.com/ElementsProject/lightning/pull/7101
[#6990]: https://github.com/ElementsProject/lightning/pull/6990
[#7178]: https://github.com/ElementsProject/lightning/pull/7178
[#7188]: https://github.com/ElementsProject/lightning/pull/7188
[#7306]: https://github.com/ElementsProject/lightning/pull/7306
[#7037]: https://github.com/ElementsProject/lightning/pull/7037
[#7304]: https://github.com/ElementsProject/lightning/pull/7304
[#7280]: https://github.com/ElementsProject/lightning/pull/7280
[#7226]: https://github.com/ElementsProject/lightning/pull/7226
[#7291]: https://github.com/ElementsProject/lightning/pull/7291
[#7235]: https://github.com/ElementsProject/lightning/pull/7235
[#7192]: https://github.com/ElementsProject/lightning/pull/7192
[#7293]: https://github.com/ElementsProject/lightning/pull/7293
[#7211]: https://github.com/ElementsProject/lightning/pull/7211
[#7237]: https://github.com/ElementsProject/lightning/pull/7237
[#7256]: https://github.com/ElementsProject/lightning/pull/7256
[24.05]: https://github.com/ElementsProject/lightning/releases/tag/v24.05
## [24.02.1] - 2024-03-08: "uint needs signature"
This release named by Erik de Smedt (@ErikDeSmedt).

2168
Cargo.lock generated

File diff suppressed because it is too large Load Diff

View File

@ -4,8 +4,10 @@ strip = "debuginfo"
[workspace]
resolver = "2"
members = [
"cln-rpc",
"cln-grpc",
"plugins",
"plugins/grpc-plugin",
"cln-rpc",
"cln-grpc",
"plugins",
"plugins/grpc-plugin",
"plugins/rest-plugin",
"plugins/lsps-plugin",
]

View File

@ -1,26 +1,35 @@
# This dockerfile is meant to compile a core-lightning x64 image
# It is using multi stage build:
# * downloader: Download litecoin/bitcoin and qemu binaries needed for core-lightning
# * builder: Compile core-lightning dependencies, then core-lightning itself with static linking
# * final: Copy the binaries required at runtime
# The resulting image uploaded to dockerhub will only contain what is needed for runtime.
# From the root of the repository, run "docker build -t yourimage:yourtag ."
# This Dockerfile is used by buildx to build ARM64, AMD64, and ARM32 Docker images from an AMD64 host.
# To speed up the build process, we are cross-compiling rather than relying on QEMU.
# There are four main stages:
# * downloader: Downloads specific binaries needed for core lightning for each architecture.
# * builder: Cross-compiles for each architecture.
# * builder-python: Builds Python dependencies for wss-proxy with QEMU.
# * final: Creates the runtime image.
FROM --platform=$BUILDPLATFORM debian:bullseye-slim as base-downloader
ARG DEFAULT_TARGETPLATFORM="linux/amd64"
ARG BASE_DISTRO="debian:bookworm-slim"
FROM --platform=$BUILDPLATFORM ${BASE_DISTRO} AS base-downloader
RUN set -ex \
&& apt-get update \
&& apt-get install -qq --no-install-recommends ca-certificates dirmngr wget
&& apt-get install -qq --no-install-recommends ca-certificates dirmngr wget qemu-user-static binfmt-support
FROM --platform=$BUILDPLATFORM base-downloader as base-downloader-linux-amd64
FROM base-downloader AS base-downloader-linux-amd64
ENV TARBALL_ARCH_FINAL=x86_64-linux-gnu
ENV DESCHASHPLUGIN_ARCH=linux-amd64
ENV DESCHASHPLUGIN_HASH=deadc00c68fac80b2718d92f69bf06acd8fff646228d497bbb76a4f0a12ca217
FROM --platform=$BUILDPLATFORM base-downloader as base-downloader-linux-arm64
FROM base-downloader AS base-downloader-linux-arm64
ENV TARBALL_ARCH_FINAL=aarch64-linux-gnu
ENV DESCHASHPLUGIN_ARCH=linux-arm64
ENV DESCHASHPLUGIN_HASH=d48c3e5aede77bd9cb72d78689ce12c0327f624435cb0496b3eacb92df416363
FROM --platform=$BUILDPLATFORM base-downloader as base-downloader-linux-arm
FROM base-downloader AS base-downloader-linux-arm
ENV TARBALL_ARCH_FINAL=arm-linux-gnueabihf
ENV DESCHASHPLUGIN_ARCH=linux-arm
ENV DESCHASHPLUGIN_HASH=f7df336c72dd1674bd18ff23862a410b6a9691a3e13752264dcffa0950e21c74
FROM base-downloader-${TARGETOS}-${TARGETARCH} as downloader
FROM base-downloader-${TARGETOS}-${TARGETARCH} AS downloader
RUN set -ex \
&& apt-get update \
@ -29,7 +38,7 @@ RUN set -ex \
WORKDIR /opt
ARG BITCOIN_VERSION=22.0
ENV BITCOIN_VERSION=27.1
ENV BITCOIN_TARBALL bitcoin-${BITCOIN_VERSION}-${TARBALL_ARCH_FINAL}.tar.gz
ENV BITCOIN_URL https://bitcoincore.org/bin/bitcoin-core-$BITCOIN_VERSION/$BITCOIN_TARBALL
ENV BITCOIN_ASC_URL https://bitcoincore.org/bin/bitcoin-core-$BITCOIN_VERSION/SHA256SUMS
@ -52,27 +61,36 @@ RUN mkdir /opt/litecoin && cd /opt/litecoin \
&& tar -xzvf litecoin.tar.gz litecoin-$LITECOIN_VERSION/bin/litecoin-cli --strip-components=1 --exclude=*-qt \
&& rm litecoin.tar.gz
FROM debian:bullseye-slim as builder
ENV DESCHASHPLUGIN_URL https://github.com/nbd-wtf/invoicewithdescriptionhash/releases/download/v1.4/invoicewithdescriptionhash-v1.4-${DESCHASHPLUGIN_ARCH}.tar.gz
ENV DESCHASHPLUGIN_SHA256 ${DESCHASHPLUGIN_HASH}
RUN mkdir /opt/deschashplugin && cd /opt/deschashplugin \
&& wget -qO invoicewithdescriptionhash.tar.gz "$DESCHASHPLUGIN_URL" \
&& echo "$DESCHASHPLUGIN_SHA256 invoicewithdescriptionhash.tar.gz" | sha256sum -c - \
&& tar -xzvf invoicewithdescriptionhash.tar.gz && rm invoicewithdescriptionhash.tar.gz \
&& chmod a+x invoicewithdescriptionhash
ENV LIGHTNINGD_VERSION=master
FROM --platform=${DEFAULT_TARGETPLATFORM} ${BASE_DISTRO} AS base-builder
RUN apt-get update -qq && \
apt-get install -qq -y --no-install-recommends \
autoconf \
automake \
bison \
build-essential \
ca-certificates \
curl \
dirmngr \
flex \
gettext \
git \
gnupg \
libpq-dev \
jq \
libicu-dev \
libtool \
libffi-dev \
pkg-config \
libssl-dev \
protobuf-compiler \
python3.9 \
python3 \
python3-dev \
python3-mako \
python3-pip \
@ -82,80 +100,245 @@ RUN apt-get update -qq && \
libevent-dev \
qemu-user-static \
wget \
jq
unzip \
tclsh
RUN wget -q https://zlib.net/fossils/zlib-1.2.13.tar.gz \
&& tar xvf zlib-1.2.13.tar.gz \
&& cd zlib-1.2.13 \
&& ./configure \
&& make \
&& make install && cd .. && \
rm zlib-1.2.13.tar.gz && \
rm -rf zlib-1.2.13
ENV PATH="/root/.local/bin:$PATH" \
PYTHON_VERSION=3 \
POETRY_VERSION=2.0.1
RUN curl -sSL https://install.python-poetry.org | python3 - && \
poetry self add poetry-plugin-export
RUN mkdir -p /root/.venvs && \
python3 -m venv /root/.venvs/cln && \
. /root/.venvs/cln/bin/activate && \
pip3 install --upgrade pip setuptools wheel
RUN apt-get install -y --no-install-recommends unzip tclsh \
&& wget -q https://www.sqlite.org/2019/sqlite-src-3290000.zip \
&& unzip sqlite-src-3290000.zip \
&& cd sqlite-src-3290000 \
&& ./configure --enable-static --disable-readline --disable-threadsafe --disable-load-extension \
&& make \
&& make install && cd .. && rm sqlite-src-3290000.zip && rm -rf sqlite-src-3290000
USER root
ENV RUST_PROFILE=release
ENV PATH=$PATH:/root/.cargo/bin/
RUN curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y
RUN rustup toolchain install stable --component rustfmt --allow-downgrade
RUN wget -q https://zlib.net/fossils/zlib-1.2.13.tar.gz -O zlib.tar.gz && \
wget -q https://www.sqlite.org/2019/sqlite-src-3290000.zip -O sqlite.zip && \
wget -q https://ftp.postgresql.org/pub/source/v17.1/postgresql-17.1.tar.gz -O postgres.tar.gz
WORKDIR /opt/lightningd
COPY . /tmp/lightning
RUN git clone --recursive /tmp/lightning . && \
git checkout $(git --work-tree=/tmp/lightning --git-dir=/tmp/lightning/.git rev-parse HEAD)
# Do not build python plugins (wss-proxy) here, python doesn't support cross compilation.
RUN sed -i '/^wss-proxy/d' pyproject.toml && \
poetry lock && \
poetry export -o requirements.txt --without-hashes
RUN mkdir -p /root/.venvs && \
python3 -m venv /root/.venvs/cln && \
. /root/.venvs/cln/bin/activate && \
pip3 install -r requirements.txt && \
pip3 cache purge
WORKDIR /
FROM base-builder AS base-builder-linux-amd64
ENV POSTGRES_CONFIG="--without-readline" \
PG_CONFIG=/usr/local/pgsql/bin/pg_config
FROM base-builder AS base-builder-linux-arm64
ENV target_host=aarch64-linux-gnu \
target_host_rust=aarch64-unknown-linux-gnu \
target_host_qemu=qemu-aarch64-static
RUN apt-get install -qq -y --no-install-recommends \
libc6-arm64-cross \
gcc-${target_host} \
g++-${target_host}
ENV AR=${target_host}-ar \
AS=${target_host}-as \
CC=${target_host}-gcc \
CXX=${target_host}-g++ \
LD=${target_host}-ld \
STRIP=${target_host}-strip \
QEMU_LD_PREFIX=/usr/${target_host} \
HOST=${target_host} \
TARGET=${target_host_rust} \
RUSTUP_INSTALL_OPTS="--target ${target_host_rust} --default-host ${target_host_rust}" \
PKG_CONFIG_PATH="/usr/${target_host}/lib/pkgconfig"
ENV ZLIB_CONFIG="--prefix=${QEMU_LD_PREFIX}" \
SQLITE_CONFIG="--host=${target_host} --prefix=${QEMU_LD_PREFIX}" \
POSTGRES_CONFIG="--without-readline --prefix=${QEMU_LD_PREFIX}" \
PG_CONFIG="${QEMU_LD_PREFIX}/bin/pg_config"
FROM base-builder AS base-builder-linux-arm
ENV target_host=arm-linux-gnueabihf \
target_host_rust=armv7-unknown-linux-gnueabihf \
target_host_qemu=qemu-arm-static
RUN apt-get install -qq -y --no-install-recommends \
libc6-armhf-cross \
gcc-${target_host} \
g++-${target_host}
ENV AR=${target_host}-ar \
AS=${target_host}-as \
CC=${target_host}-gcc \
CXX=${target_host}-g++ \
LD=${target_host}-ld \
STRIP=${target_host}-strip \
QEMU_LD_PREFIX=/usr/${target_host} \
HOST=${target_host} \
TARGET=${target_host_rust} \
RUSTUP_INSTALL_OPTS="--target ${target_host_rust} --default-host ${target_host_rust}" \
PKG_CONFIG_PATH="/usr/${target_host}/lib/pkgconfig"
ENV ZLIB_CONFIG="--prefix=${QEMU_LD_PREFIX}" \
SQLITE_CONFIG="--host=${target_host} --prefix=${QEMU_LD_PREFIX}" \
POSTGRES_CONFIG="--without-readline --prefix=${QEMU_LD_PREFIX}" \
PG_CONFIG="${QEMU_LD_PREFIX}/bin/pg_config"
FROM base-builder-${TARGETOS}-${TARGETARCH} AS builder
ENV LIGHTNINGD_VERSION=master
RUN mkdir zlib && tar xvf zlib.tar.gz -C zlib --strip-components=1 \
&& cd zlib \
&& ./configure ${ZLIB_CONFIG} \
&& make \
&& make install && cd .. && \
rm zlib.tar.gz && \
rm -rf zlib
RUN unzip sqlite.zip \
&& cd sqlite-* \
&& ./configure --enable-static --disable-readline --disable-threadsafe --disable-load-extension ${SQLITE_CONFIG} \
&& make \
&& make install && cd .. && rm sqlite.zip && rm -rf sqlite-*
RUN mkdir postgres && tar xvf postgres.tar.gz -C postgres --strip-components=1 \
&& cd postgres \
&& ./configure ${POSTGRES_CONFIG} \
&& cd src/include \
&& make install \
&& cd ../interfaces/libpq \
&& make install \
&& cd ../../bin/pg_config \
&& make install \
&& cd ../../../../ && \
rm postgres.tar.gz && \
rm -rf postgres && \
ldconfig "$(${PG_CONFIG} --libdir)"
# Save libpq to a specific location to copy it into the final image.
RUN mkdir /var/libpq && cp -a "$(${PG_CONFIG} --libdir)"/libpq.* /var/libpq
ENV RUST_PROFILE=release \
PATH="/root/.cargo/bin:/root/.local/bin:$PATH"
RUN curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y ${RUSTUP_INSTALL_OPTS}
RUN rustup toolchain install stable --component rustfmt --allow-downgrade
COPY --from=downloader /usr/bin/${target_host_qemu} /usr/bin/${target_host_qemu}
WORKDIR /opt/lightningd
# If cross-compiling, need to tell it to cargo.
RUN ( ! [ -n "${target_host}" ] ) || \
(mkdir -p .cargo && echo "[target.${target_host_rust}]\nlinker = \"${target_host}-gcc\"" > .cargo/config)
# Weird errors with cargo for cln-grpc on arm7 https://github.com/ElementsProject/lightning/issues/6596
RUN ( ! [ "${target_host}" = "arm-linux-gnueabihf" ] ) || \
(sed -i '/documentation = "https:\/\/docs.rs\/cln-grpc"/a include = ["**\/*.*"]' cln-grpc/Cargo.toml)
# Ensure that the desired grpcio-tools & protobuf versions are installed
# https://github.com/ElementsProject/lightning/pull/7376#issuecomment-2161102381
RUN poetry lock && poetry install && \
poetry self add poetry-plugin-export
# Ensure that git differences are removed before making bineries, to avoid `-modded` suffix
# poetry.lock changed due to pyln-client, pyln-proto and pyln-testing version updates
# pyproject.toml was updated to exclude wss-proxy plugins in base-builder stage
RUN git reset --hard HEAD
RUN ./configure --prefix=/tmp/lightning_install --enable-static && poetry run make install
# Export the requirements for the plugins so we can install them in builder-python stage
WORKDIR /opt/lightningd/plugins/wss-proxy
RUN poetry lock && poetry export -o requirements.txt --without-hashes
WORKDIR /opt/lightningd
RUN echo 'RUSTUP_INSTALL_OPTS="${RUSTUP_INSTALL_OPTS}"' > /tmp/rustup_install_opts.txt
# We need to build python plugins on the target's arch because python doesn't support cross build
FROM ${BASE_DISTRO} AS builder-python
RUN apt-get update -qq && \
apt-get install -qq -y --no-install-recommends \
git \
curl \
libtool \
pkg-config \
autoconf \
automake \
build-essential \
libffi-dev \
libssl-dev \
python3 \
python3-dev \
python3-pip \
python3-venv && \
apt-get clean && \
rm -rf /var/lib/apt/lists/*
ENV PYTHON_VERSION=3
RUN curl -sSL https://install.python-poetry.org | python3 -
RUN mkdir -p /root/.venvs && \
python3 -m venv /root/.venvs/cln && \
. /root/.venvs/cln/bin/activate && \
pip3 install --upgrade pip setuptools wheel
RUN update-alternatives --install /usr/bin/python python /usr/bin/python3.9 1
# Copy rustup_install_opts.txt file from builder
COPY --from=builder /tmp/rustup_install_opts.txt /tmp/rustup_install_opts.txt
# Setup ENV $RUSTUP_INSTALL_OPTS for this stage
RUN export $(cat /tmp/rustup_install_opts.txt)
ENV PATH="/root/.cargo/bin:/root/.venvs/cln/bin:$PATH"
RUN curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y ${RUSTUP_INSTALL_OPTS}
RUN pip3 install --upgrade pip setuptools wheel
RUN pip3 wheel cryptography
RUN pip3 install grpcio-tools
RUN /root/.local/bin/poetry export -o requirements.txt --without-hashes --with dev
WORKDIR /opt/lightningd/plugins/wss-proxy
COPY --from=builder /opt/lightningd/plugins/wss-proxy/requirements.txt .
RUN pip3 install -r requirements.txt
RUN pip3 cache purge
RUN ./configure --prefix=/tmp/lightning_install --enable-static && \
make && \
/root/.local/bin/poetry run make install
WORKDIR /opt/lightningd
FROM debian:bullseye-slim as final
FROM ${BASE_DISTRO} AS final
RUN apt-get update && \
apt-get install -y --no-install-recommends \
tini \
socat \
inotify-tools \
python3.9 \
python3-pip \
qemu-user-static \
libpq5 && \
jq \
python3 \
python3-pip && \
apt-get clean && \
rm -rf /var/lib/apt/lists/*
ENV LIGHTNINGD_DATA=/root/.lightning
ENV LIGHTNINGD_RPC_PORT=9835
ENV LIGHTNINGD_PORT=9735
ENV LIGHTNINGD_NETWORK=bitcoin
ENV LIGHTNINGD_DATA=/root/.lightning \
LIGHTNINGD_RPC_PORT=9835 \
LIGHTNINGD_PORT=9735 \
LIGHTNINGD_NETWORK=bitcoin
RUN mkdir $LIGHTNINGD_DATA && \
mkdir /etc/bundledplugins && \
mkdir $LIGHTNINGD_DATA/plugins && \
touch $LIGHTNINGD_DATA/config
VOLUME [ "/root/.lightning" ]
# Take libpq directly from builder.
RUN mkdir /var/libpq && mkdir -p /usr/local/pgsql/lib
RUN --mount=type=bind,from=builder,source=/var/libpq,target=/var/libpq,rw \
cp -a /var/libpq/libpq.* /usr/local/pgsql/lib && \
echo "/usr/local/pgsql/lib" > /etc/ld.so.conf.d/libpq.conf && \
ldconfig
COPY --from=builder /tmp/lightning_install/ /usr/local/
COPY --from=builder /usr/local/lib/python3.9/dist-packages/ /usr/local/lib/python3.9/dist-packages/
COPY --from=builder-python /root/.venvs/cln/lib/python3.11/site-packages /usr/local/lib/python3.11/dist-packages/
COPY --from=downloader /opt/bitcoin/bin /usr/bin
COPY --from=downloader /opt/litecoin/bin /usr/bin
COPY --from=downloader /opt/deschashplugin $LIGHTNINGD_DATA/plugins
COPY --from=downloader /opt/deschashplugin /etc/bundledplugins
COPY tools/docker-entrypoint.sh entrypoint.sh
EXPOSE 9735 9835

133
Makefile
View File

@ -1,10 +1,10 @@
#! /usr/bin/make
# Extract version from git, or if we're from a zipfile, use dirname
VERSION=$(shell git describe --always --dirty=-modded --abbrev=7 2>/dev/null || pwd | sed -n 's|.*/c\{0,1\}lightning-v\{0,1\}\([0-9a-f.rc\-]*\)$$|\1|gp')
VERSION=$(shell git describe --tags --always --dirty=-modded --abbrev=7 2>/dev/null || pwd | sed -n 's|.*/c\{0,1\}lightning-v\{0,1\}\([0-9a-f.rc\-]*\)$$|v\1|gp')
# Next release.
CLN_NEXT_VERSION := v24.05
CLN_NEXT_VERSION := v25.05
# --quiet / -s means quiet, dammit!
ifeq ($(findstring s,$(word 1, $(MAKEFLAGS))),s)
@ -26,7 +26,7 @@ CCANDIR := ccan
# Where we keep the BOLT RFCs
BOLTDIR := ../bolts/
DEFAULT_BOLTVERSION := 6e85df448bfee7d10f26aabb06b8eba3d7505888
DEFAULT_BOLTVERSION := ccfa38ed4f592c3711156bb4ded77f44ec01101d
# Can be overridden on cmdline.
BOLTVERSION := $(DEFAULT_BOLTVERSION)
@ -36,7 +36,7 @@ SORT=LC_ALL=C sort
ifeq ($V,1)
VERBOSE = $(ECHO) '$(2)'; $(2)
VERBOSE = $(ECHO) '$(subst ','\'',$(2))'; $(2)
else
VERBOSE = $(ECHO) $(1); $(2)
endif
@ -72,7 +72,7 @@ endif
# (method=thread to support xdist)
PYTEST_OPTS := -v -p no:logging $(PYTEST_OPTS)
MY_CHECK_PYTHONPATH=$${PYTHONPATH}$${PYTHONPATH:+:}$(shell pwd)/contrib/pyln-client:$(shell pwd)/contrib/pyln-testing:$(shell pwd)/contrib/pyln-proto/:$(shell pwd)/contrib/pyln-spec/bolt1:$(shell pwd)/contrib/pyln-spec/bolt2:$(shell pwd)/contrib/pyln-spec/bolt4:$(shell pwd)/contrib/pyln-spec/bolt7
MY_CHECK_PYTHONPATH=$${PYTHONPATH}$${PYTHONPATH:+:}$(shell pwd)/contrib/pyln-client:$(shell pwd)/contrib/pyln-testing:$(shell pwd)/contrib/pyln-proto/:$(shell pwd)/contrib/pyln-spec/bolt1:$(shell pwd)/contrib/pyln-spec/bolt2:$(shell pwd)/contrib/pyln-spec/bolt4:$(shell pwd)/contrib/pyln-spec/bolt7:$(shell pwd)/contrib/pyln-grpc-proto
# Collect generated python files to be excluded from lint checks
PYTHON_GENERATED= \
contrib/pyln-grpc-proto/pyln/grpc/primitives_pb2.py \
@ -80,10 +80,6 @@ PYTHON_GENERATED= \
contrib/pyln-grpc-proto/pyln/grpc/node_pb2.py \
contrib/pyln-testing/pyln/testing/grpc2py.py
# Options to pass to cppcheck. Mostly used to exclude files that are
# generated with external tools that we don't have control over
CPPCHECK_OPTS=-q --language=c --std=c11 --error-exitcode=1 --suppressions-list=.cppcheck-suppress --inline-suppr
# This is where we add new features as bitcoin adds them.
FEATURES :=
@ -232,10 +228,24 @@ ALL_TEST_PROGRAMS :=
ALL_TEST_GEN :=
ALL_FUZZ_TARGETS :=
ALL_C_SOURCES :=
ALL_C_HEADERS := header_versions_gen.h version_gen.h
ALL_C_HEADERS :=
# Extra (non C) targets that should be built by default.
DEFAULT_TARGETS :=
# Installation directories
exec_prefix = $(PREFIX)
bindir = $(exec_prefix)/bin
libexecdir = $(exec_prefix)/libexec
pkglibexecdir = $(libexecdir)/$(PKGNAME)
plugindir = $(pkglibexecdir)/plugins
datadir = $(PREFIX)/share
docdir = $(datadir)/doc/$(PKGNAME)
mandir = $(datadir)/man
man1dir = $(mandir)/man1
man5dir = $(mandir)/man5
man7dir = $(mandir)/man7
man8dir = $(mandir)/man8
# M1 macos machines with homebrew will install the native libraries in
# /opt/homebrew instead of /usr/local, most likely because they
# emulate x86_64 compatibility via Rosetta, and wanting to keep the
@ -252,8 +262,8 @@ CPATH := /usr/local/include
LIBRARY_PATH := /usr/local/lib
endif
CPPFLAGS += -DCLN_NEXT_VERSION="\"$(CLN_NEXT_VERSION)\"" -DBINTOPKGLIBEXECDIR="\"$(shell sh tools/rel.sh $(bindir) $(pkglibexecdir))\""
CFLAGS = $(CPPFLAGS) $(CWARNFLAGS) $(CDEBUGFLAGS) $(COPTFLAGS) -I $(CCANDIR) $(EXTERNAL_INCLUDE_FLAGS) -I . -I$(CPATH) $(SQLITE3_CFLAGS) $(POSTGRES_INCLUDE) $(FEATURES) $(COVFLAGS) $(DEV_CFLAGS) -DSHACHAIN_BITS=48 -DJSMN_PARENT_LINKS $(PIE_CFLAGS) $(COMPAT_CFLAGS) $(CSANFLAGS)
CPPFLAGS += -DCLN_NEXT_VERSION="\"$(CLN_NEXT_VERSION)\"" -DPKGLIBEXECDIR="\"$(pkglibexecdir)\"" -DBINDIR="\"$(bindir)\"" -DPLUGINDIR="\"$(plugindir)\"" -DCCAN_TAL_NEVER_RETURN_NULL=1
CFLAGS = $(CPPFLAGS) $(CWARNFLAGS) $(CDEBUGFLAGS) $(COPTFLAGS) -I $(CCANDIR) $(EXTERNAL_INCLUDE_FLAGS) -I . -I$(CPATH) $(SQLITE3_CFLAGS) $(SODIUM_CFLAGS) $(POSTGRES_INCLUDE) $(FEATURES) $(COVFLAGS) $(DEV_CFLAGS) -DSHACHAIN_BITS=48 -DJSMN_PARENT_LINKS $(PIE_CFLAGS) $(COMPAT_CFLAGS) $(CSANFLAGS)
# If CFLAGS is already set in the environment of make (to whatever value, it
# does not matter) then it would export it to subprocesses with the above value
@ -271,9 +281,9 @@ ifeq ($(STATIC),1)
# For MacOS, Jacob Rapoport <jacob@rumblemonkey.com> changed this to:
# -L/usr/local/lib -lsqlite3 -lz -Wl,-lm -lpthread -ldl $(COVFLAGS)
# But that doesn't static link.
LDLIBS = -L$(CPATH) -Wl,-dn $(SQLITE3_LDLIBS) -lz -Wl,-dy -lm -lpthread -ldl $(COVFLAGS)
LDLIBS = -L$(CPATH) -Wl,-dn $(SQLITE3_LDLIBS) -Wl,-dy -lm -lpthread -ldl $(COVFLAGS)
else
LDLIBS = -L$(CPATH) -lm $(SQLITE3_LDLIBS) -lz $(COVFLAGS)
LDLIBS = -L$(CPATH) -lm $(SQLITE3_LDLIBS) $(COVFLAGS)
endif
# If we have the postgres client library we need to link against it as well
@ -359,19 +369,23 @@ include doc/Makefile
include contrib/msggen/Makefile
include devtools/Makefile
include tools/Makefile
ifneq ($(RUST),0)
include cln-rpc/Makefile
include cln-grpc/Makefile
endif
include plugins/Makefile
include tests/plugins/Makefile
ifneq ($(FUZZING),0)
include tests/fuzz/Makefile
endif
ifneq ($(RUST),0)
include cln-rpc/Makefile
ifneq ($V,1)
MSGGEN_ARGS := -s
endif
include cln-grpc/Makefile
$(MSGGEN_GENALL)&: contrib/msggen/msggen/schema.json
PYTHONPATH=contrib/msggen $(PYTHON) contrib/msggen/msggen/__main__.py generate
@$(call VERBOSE, "msggen $@", PYTHONPATH=contrib/msggen $(PYTHON) contrib/msggen/msggen/__main__.py $(MSGGEN_ARGS) generate)
# The compiler assumes that the proto files are in the same
# directory structure as the generated files will be. Since we
@ -452,6 +466,11 @@ else
PYTEST_OPTS += -x
endif
# Allow for targeting specific tests by setting the PYTEST_TESTS environment variable.
ifeq ($(PYTEST_TESTS),)
PYTEST_TESTS = "tests/"
endif
check-units:
check: check-units installcheck pytest
@ -462,7 +481,7 @@ ifeq ($(PYTEST),)
exit 1
else
# Explicitly hand VALGRIND so you can override on make cmd line.
PYTHONPATH=$(MY_CHECK_PYTHONPATH) TEST_DEBUG=1 VALGRIND=$(VALGRIND) $(PYTEST) tests/ $(PYTEST_OPTS)
PYTHONPATH=$(MY_CHECK_PYTHONPATH) TEST_DEBUG=1 VALGRIND=$(VALGRIND) $(PYTEST) $(PYTEST_TESTS) $(PYTEST_OPTS)
endif
check-fuzz: $(ALL_FUZZ_TARGETS)
@ -540,13 +559,6 @@ check-pytest-pyln-proto:
check-includes: check-src-includes check-hdr-includes
@tools/check-includes.sh
# cppcheck gets confused by list_for_each(head, i, list): thinks i is uninit.
.cppcheck-suppress:
@git ls-files -z -- "*.c" "*.h" | grep -vzE '^(ccan|contrib)/' | xargs -0 grep -n '_for_each' | sed 's/\([^:]*:.*\):.*/uninitvar:\1/' > $@
check-cppcheck: .cppcheck-suppress
@trap 'rm -f .cppcheck-suppress' 0; git ls-files -z -- "*.c" "*.h" | grep -vzE '^ccan/' | xargs -0 cppcheck ${CPPCHECK_OPTS}
check-shellcheck:
@git ls-files -z -- "*.sh" | xargs -0 shellcheck -f gcc
@ -563,12 +575,29 @@ check-discouraged-functions:
# since it risks overflow.
check-amount-access:
@! (git grep -nE "(->|\.)(milli)?satoshis" -- "*.c" "*.h" ":(exclude)common/amount.*" ":(exclude)*/test/*" | grep -v '/* Raw:')
@! git grep -nE "\\(struct amount_(m)?sat\\)" -- "*.c" "*.h" ":(exclude)common/amount.*" ":(exclude)*/test/*"
@! git grep -nE "\\(struct amount_(m)?sat\\)" -- "*.c" "*.h" ":(exclude)common/amount.*" ":(exclude)*/test/*" | grep -vE "sizeof.struct amount_(m)?sat."
repeat-doc-examples:
@for i in $$(seq 1 $(n)); do \
echo "----------------------------------" >> tests/autogenerate-examples-repeat.log; \
echo "Iteration $$i" >> tests/autogenerate-examples-repeat.log; \
echo "----------------------------------" >> tests/autogenerate-examples-repeat.log; \
VALGRIND=0 TIMEOUT=40 TEST_DEBUG=1 GENERATE_EXAMPLES=1 pytest -vvv tests/autogenerate-rpc-examples.py; \
git diff >> tests/autogenerate-examples-repeat.log; \
git reset --hard; \
echo "----------------------------------" >> tests/autogenerate-examples-repeat.log; \
done
update-doc-examples:
TEST_DEBUG=1 VALGRIND=0 GENERATE_EXAMPLES=1 $(PYTEST) $(PYTEST_OPTS) --timeout=1200 tests/autogenerate-rpc-examples.py && $(MAKE) $(MSGGEN_GEN_ALL)
check-doc-examples: update-doc-examples
git diff --exit-code HEAD
# For those without working cppcheck
check-source-no-cppcheck: check-makefile check-source-bolt check-whitespace check-spelling check-python check-includes check-shellcheck check-setup_locale check-tmpctx check-discouraged-functions check-amount-access
check-source: check-source-no-cppcheck check-cppcheck
check-source: check-source-no-cppcheck
full-check: check check-source
@ -636,7 +665,7 @@ version_gen.h: $(FORCE)
endif
# That forces this rule to be run every time, too.
header_versions_gen.h: tools/headerversions
header_versions_gen.h: tools/headerversions $(FORCE)
@tools/headerversions $@
# We make a static library, this way linker can discard unused parts.
@ -654,7 +683,7 @@ $(ALL_TEST_PROGRAMS) $(ALL_FUZZ_TARGETS): %: %.o
# uses some ccan modules internally). We want to rely on -lwallycore etc.
# (as per EXTERNAL_LDLIBS) so we filter them out here.
$(ALL_PROGRAMS) $(ALL_TEST_PROGRAMS):
@$(call VERBOSE, "ld $@", $(LINK.o) $(filter-out %.a,$^) $(LOADLIBES) $(EXTERNAL_LDLIBS) $(LDLIBS) libccan.a -o $@)
@$(call VERBOSE, "ld $@", $(LINK.o) $(filter-out %.a,$^) $(LOADLIBES) $(EXTERNAL_LDLIBS) $(LDLIBS) libccan.a $($(@)_LDLIBS) -o $@)
# We special case the fuzzing target binaries, as they need to link against libfuzzer,
# which brings its own main().
@ -685,6 +714,7 @@ update-ccan:
# Now ALL_PROGRAMS is fully populated, we can expand it.
all-programs: $(ALL_PROGRAMS)
all-fuzz-programs: $(ALL_FUZZ_TARGETS)
all-test-programs: $(ALL_TEST_PROGRAMS) $(ALL_FUZZ_TARGETS)
default-targets: $(DEFAULT_TARGETS)
@ -697,8 +727,10 @@ maintainer-clean: distclean
$(RM) $(PYTHON_GENERATED)
# We used to have gen_ files, now we have _gen files.
# We used to generate doc/schemas/lightning-sql.json.
obsclean:
$(RM) gen_*.h */gen_*.[ch] */*/gen_*.[ch]
$(RM) doc/schemas/lightning-sql.json
clean: obsclean
$(RM) libccan.a $(CCAN_OBJS) $(CDUMP_OBJS) $(ALL_OBJS)
@ -717,7 +749,7 @@ clean: obsclean
PYLNS=client proto testing
# See doc/contribute-to-core-lightning/contributor-workflow.md
update-py-versions: update-pyln-versions update-clnrest-version update-poetry-lock
update-versions: update-pyln-versions update-wss-proxy-version update-poetry-lock update-dot-version update-doc-examples
update-pyln-versions: $(PYLNS:%=update-pyln-version-%)
@ -730,12 +762,20 @@ pyln-release: $(PYLNS:%=pyln-release-%)
pyln-release-%:
cd contrib/pyln-$* && $(MAKE) prod-release
update-clnrest-version:
update-wss-proxy-version:
@if [ -z "$(NEW_VERSION)" ]; then echo "Set NEW_VERSION!" >&2; exit 1; fi
cd plugins/clnrest && $(MAKE) upgrade-version
cd plugins/wss-proxy && $(MAKE) upgrade-version
update-poetry-lock:
poetry update clnrest pyln-client pyln-proto pyln-testing
poetry update wss-proxy pyln-client pyln-proto pyln-testing update-reckless-version
update-reckless-version:
@if [ -z "$(NEW_VERSION)" ]; then echo "Set NEW_VERSION!" >&2; exit 1; fi
@sed -i "s/__VERSION__ = '\([.-z]*\)'/__VERSION__ = '$(NEW_VERSION)'/" tools/reckless
update-dot-version:
@if [ -z "$(NEW_VERSION)" ]; then echo "Set NEW_VERSION!" >&2; exit 1; fi
echo $(NEW_VERSION) > .version
update-mocks: $(ALL_TEST_PROGRAMS:%=update-mocks/%.c)
@ -744,22 +784,8 @@ $(ALL_TEST_PROGRAMS:%=update-mocks/%.c): $(ALL_GEN_HEADERS) $(EXTERNAL_LIBS) lib
update-mocks/%: % $(ALL_GEN_HEADERS) $(ALL_GEN_SOURCES)
@MAKE=$(MAKE) tools/update-mocks.sh "$*" $(SUPPRESS_OUTPUT)
unittest/%: %
$(VG) $(VG_TEST_ARGS) $* > /dev/null
# Installation directories
exec_prefix = $(PREFIX)
bindir = $(exec_prefix)/bin
libexecdir = $(exec_prefix)/libexec
pkglibexecdir = $(libexecdir)/$(PKGNAME)
plugindir = $(pkglibexecdir)/plugins
datadir = $(PREFIX)/share
docdir = $(datadir)/doc/$(PKGNAME)
mandir = $(datadir)/man
man1dir = $(mandir)/man1
man5dir = $(mandir)/man5
man7dir = $(mandir)/man7
man8dir = $(mandir)/man8
unittest/%: % bolt-precheck
BOLTDIR=$(LOCAL_BOLTDIR) $(VG) $(VG_TEST_ARGS) $* > /dev/null
# Commands
MKDIR_P = mkdir -p
@ -793,6 +819,7 @@ install-program: installdirs $(BIN_PROGRAMS) $(PKGLIBEXEC_PROGRAMS) $(PLUGINS) $
@$(NORMAL_INSTALL)
$(INSTALL_PROGRAM) $(BIN_PROGRAMS) $(DESTDIR)$(bindir)
$(INSTALL_PROGRAM) $(PKGLIBEXEC_PROGRAMS) $(DESTDIR)$(pkglibexecdir)
@if [ -d "$(DESTDIR)$(plugindir)/clnrest" ]; then rm -rf $(DESTDIR)$(plugindir)/clnrest; fi
[ -z "$(PLUGINS)" ] || $(INSTALL_PROGRAM) $(PLUGINS) $(DESTDIR)$(plugindir)
for PY in $(PY_PLUGINS); do DIR=`dirname $$PY`; DST=$(DESTDIR)$(plugindir)/`basename $$DIR`; if [ -d $$DST ]; then rm -rf $$DST; fi; $(INSTALL_PROGRAM) -d $$DIR; cp -a $$DIR $$DST ; done
@ -819,6 +846,7 @@ install: install-program install-data
TESTBINS = \
$(CLN_PLUGIN_EXAMPLES) \
tests/plugins/test_libplugin \
tests/plugins/channeld_fakenet \
tests/plugins/test_selfdisable_after_getmanifest \
tools/hsmtool
@ -882,8 +910,11 @@ installcheck: all-programs
fi
@rm -rf testinstall || true
version:
@echo ${VERSION}
.PHONY: installdirs install-program install-data install uninstall \
installcheck ncc bin-tarball show-flags
installcheck ncc bin-tarball show-flags version
# Make a tarball of opt/clightning/, optionally with label for distribution.
ifneq ($(VERSION),)

View File

@ -19,25 +19,30 @@ Core Lightning (previously c-lightning) is a lightweight, highly customizable an
## Project Status
[![Continuous Integration](https://github.com/ElementsProject/lightning/workflows/Continuous%20Integration/badge.svg)][actions]
[![Pull Requests Welcome][prs]][prs-link]
[![Irc][IRC]][IRC-link]
[![Documentation Status](https://readthedocs.org/projects/lightning/badge/?version=docs)][docs]
[![Continuous Integration][actions-badge]][actions]
[![Pull Requests Welcome][prs-badge]][prs]
[![Documentation Status][docs-badge]][docs]
[![BoL2][bol2-badge]][bol2]
[![Telegram][telegram-badge]][telegram]
[![Discord][discord-badge]][discord]
[![Irc][IRC-badge]][IRC]
This implementation has been in production use on the Bitcoin mainnet since early 2018, with the launch of the [Blockstream Store][blockstream-store-blog].
We recommend getting started by experimenting on `testnet` (or `regtest`), but the implementation is considered stable and can be safely used on mainnet.
We recommend getting started by experimenting on `testnet` (`testnet4` or `regtest`), but the implementation is considered stable and can be safely used on mainnet.
## Reach Out to Us
Any help testing the implementation, reporting bugs, or helping with outstanding issues is very welcome.
Don't hesitate to reach out to us on IRC at [#lightning-dev @ libera.chat][irc1], [#c-lightning @ libera.chat][irc2], or on the implementation-specific mailing list [c-lightning@lists.ozlabs.org][ml1], or on the Lightning Network-wide mailing list [lightning-dev@lists.linuxfoundation.org][ml2], or on Discord [core-lightning][discord], or on Telegram [Core Lightning][telegram].
Don't hesitate to reach out to us on [Build-on-L2][bol2], or on the implementation-specific [mailing list][ml1], or on [CLN Discord][discord], or on [CLN Telegram][telegram], or on IRC at [dev][irc1]/[gen][irc2] channel.
## Getting Started
Core Lightning only works on Linux and macOS, and requires a locally (or remotely) running `bitcoind` (version 22.0 or above) that is fully caught up with the network you're running on, and relays transactions (ie with `blocksonly=0`).
Core Lightning only works on Linux and macOS, and requires a locally (or remotely) running `bitcoind` (version 25.0 or above) that is fully caught up with the network you're running on, and relays transactions (ie with `blocksonly=0`).
Pruning (`prune=n` option in `bitcoin.conf`) is partially supported, see [here](#pruning) for more details.
### Installation
There are 4 supported installation options:
There are 3 supported installation options:
- Installation of a pre-compiled binary from the [release page][releases] on GitHub.
- Using one of the [provided docker images][dockerhub] on the Docker Hub.
@ -101,13 +106,10 @@ the lightning network.
There are also numerous plugins available for Core Lightning which add
capabilities: in particular there's a collection at: https://github.com/lightningd/plugins
Including [helpme][helpme-github] which guides you through setting up
your first channels and customizing your node.
For a less reckless experience, you can encrypt the HD wallet seed:
see [HD wallet encryption](#hd-wallet-encryption).
You can also chat to other users at [#c-lightning @ libera.chat][irc2];
You can also chat to other users at Discord [core-lightning][discord];
we are always happy to help you get started!
@ -123,11 +125,11 @@ lightning-cli newaddr
`lightningd` will register the funds once the transaction is confirmed.
You may need to generate a p2sh-segwit address if the faucet does not support bech32:
Alternatively you can generate a taproot address should your source of funds support it:
```bash
# Return a p2sh-segwit address
lightning-cli newaddr p2sh-segwit
# Return a taproot address
lightning-cli newaddr p2tr
```
Confirm `lightningd` got funds by:
@ -207,19 +209,24 @@ Developers wishing to contribute should start with the developer guide [here](do
[blockstream-store-blog]: https://blockstream.com/2018/01/16/en-lightning-charge/
[std]: https://github.com/lightning/bolts
[prs]: https://img.shields.io/badge/PRs-welcome-brightgreen.svg?style=flat
[prs-link]: http://makeapullrequest.com
[IRC]: https://img.shields.io/badge/chat-on%20libera-brightgreen.svg
[IRC-link]: https://web.libera.chat/#c-lightning
[prs-badge]: https://img.shields.io/badge/PRs-welcome-brightgreen.svg?style=flat
[prs]: http://makeapullrequest.com
[bol2-badge]: https://badgen.net/badge/BoL2/chat/blue
[bol2]: https://community.corelightning.org
[ml1]: https://lists.ozlabs.org/listinfo/c-lightning
[discord-badge]: https://badgen.net/badge/Discord/chat/blue
[discord]: https://discord.gg/mE9s4rc5un
[telegram-badge]: https://badgen.net/badge/Telegram/chat/blue
[telegram]: https://t.me/lightningd
[IRC-badge]: https://img.shields.io/badge/IRC-chat-blue.svg
[IRC]: https://web.libera.chat/#c-lightning
[irc1]: https://web.libera.chat/#lightning-dev
[irc2]: https://web.libera.chat/#c-lightning
[ml1]: https://lists.ozlabs.org/listinfo/c-lightning
[ml2]: https://lists.linuxfoundation.org/mailman/listinfo/lightning-dev
[discord]: https://discord.gg/mE9s4rc5un
[telegram]: https://t.me/lightningd
[docs-badge]: https://readthedocs.org/projects/lightning/badge/?version=docs
[docs]: https://docs.corelightning.org/docs
[releases]: https://github.com/ElementsProject/lightning/releases
[dockerhub]: https://hub.docker.com/r/elementsproject/lightningd/
[jsonrpcspec]: https://www.jsonrpc.org/specification
[helpme-github]: https://github.com/lightningd/plugins/tree/master/helpme
[actions-badge]: https://github.com/ElementsProject/lightning/workflows/Continuous%20Integration/badge.svg
[actions]: https://github.com/ElementsProject/lightning/actions

View File

@ -6,19 +6,30 @@ We have a 3 month release cycle, and the last two versions are supported.
## Reporting a Vulnerability
To report security issues send an email to rusty@rustcorp.com.au, or
security@blockstream.com (not for support).
To report security vulnerabilities, please send an email to one of the following addresses:
- `rusty@rustcorp.com.au`
- `security@blockstream.com`
Note: These email addresses are exclusively for vulnerability reporting.
For all other inquiries/communication, please refer to the [Reach Out to Us](https://github.com/ElementsProject/lightning?tab=readme-ov-file#reach-out-to-us) section in our README.
## Signatures For Releases
The following keys may be used to communicate sensitive information to
developers, and to validate signatures on releases:
| Name | Fingerprint |
|------|-------------|
| Rusty Russell | 15EE 8D6C AB0E 7F0C F999 BFCB D920 0E6C D1AD B8F1 |
| Christian Decker | B731 AAC5 21B0 1385 9313 F674 A26D 6D9F E088 ED58 |
| Lisa Neigut | 30DE 693A E0DE 9E37 B3E7 EB6B BFF0 F678 10C1 EED1 |
| Alex Myers | 0437 4E42 789B BBA9 462E 4767 F3BF 63F2 7474 36AB |
| Name | Email | Fingerprint |
|------|-------|-------------|
| Blockstream Security Reporting | `security@blockstream.com` | 1176 542D A98E 71E1 3372 2EF7 4AC8 CC88 6844 A2D6 |
| Rusty Russell | `rusty@rustcorp.com.au` | 15EE 8D6C AB0E 7F0C F999 BFCB D920 0E6C D1AD B8F1 |
| Christian Decker | `decker@blockstream.com` | B731 AAC5 21B0 1385 9313 F674 A26D 6D9F E088 ED58 |
| Lisa Neigut | `niftynei@gmail.com` | 30DE 693A E0DE 9E37 B3E7 EB6B BFF0 F678 10C1 EED1 |
| Alex Myers | `alex@endothermic.dev` | 0437 4E42 789B BBA9 462E 4767 F3BF 63F2 7474 36AB |
| Peter Neuroth | `pet.v.ne@gmail.com` | 653B 19F3 3DF7 EFF3 E9D1 C94C C3F2 1EE3 87FF 4CD2 |
| Shahana Farooqui | `sfarooqui@blockstream.com` | FE13 58EB 7793 51DB 24E5 555A A327 573C 9758 9BF5 |
| Blockstream CLN Release | `cln@blockstream.com` | 616C 52F9 9D06 12B2 A151 B107 4129 A994 AA7E 9852 |
You can import a key by running the following command with that individuals fingerprint: `gpg --keyserver hkps://keys.openpgp.org --recv-keys "<fingerprint>"` Ensure that you put quotes around fingerprints containing spaces.
You can import a key by running the following command with that individuals fingerprint:
`gpg --keyserver hkps://keys.openpgp.org --recv-keys "<fingerprint>"`.
Ensure that you put quotes around fingerprints containing spaces.

View File

@ -1,6 +0,0 @@
---
name: 'Lightning CI'
description: 'A preconfigured container with all Core Lightning dependencies'
runs:
using: 'docker'
image: 'contrib/Dockerfile.tester'

View File

@ -137,6 +137,32 @@ const struct chainparams networks[] = {
.bip32_key_version = {.bip32_pubkey_version = BIP32_VER_TEST_PUBLIC,
.bip32_privkey_version = BIP32_VER_TEST_PRIVATE},
.is_elements = false},
{.network_name = "testnet4",
.onchain_hrp = "tb",
.lightning_hrp = "tb",
.bip70_name = "testnet4",
// 00000000da84f2bafbbc53dee25a72ae507ff4914b867c565be350b0da8bf043
.genesis_blockhash = {{{.u.u8 = {0x43, 0xf0, 0x8b, 0xda, 0xb0, 0x50, 0xe3,
0x5b, 0x56, 0x7c, 0x86, 0x4b, 0x91, 0xf4,
0x7f, 0x50, 0xae, 0x72, 0x5a, 0xe2, 0xde,
0x53, 0xbc, 0xfb, 0xba, 0xf2, 0x84, 0xda,
0x00, 0x00, 0x00, 0x00}}}},
.rpc_port = 48332,
.ln_port = 49735,
.cli = "bitcoin-cli",
.cli_args = "-testnet4",
.cli_min_supported_version = 150000,
.dust_limit = { 546 },
.max_funding = AMOUNT_SAT_INIT((1 << 24) - 1),
.max_payment = AMOUNT_MSAT_INIT(0xFFFFFFFFULL),
.max_supply = AMOUNT_SAT_INIT(2100000000000000),
.p2pkh_version = 111,
.p2sh_version = 196,
.testnet = true,
.fee_asset_tag = NULL,
.bip32_key_version = {.bip32_pubkey_version = BIP32_VER_TEST_PUBLIC,
.bip32_privkey_version = BIP32_VER_TEST_PRIVATE},
.is_elements = false},
{.network_name = "litecoin",
.onchain_hrp = "ltc",
.lightning_hrp = "ltc",

View File

@ -102,6 +102,79 @@ struct wally_psbt *combine_psbt(const tal_t *ctx,
return combined_psbt;
}
static bool parent_or_grandparent(const tal_t *goal, const tal_t *child)
{
const tal_t *parent = tal_parent(child);
if (!parent)
return false;
return parent == goal || parent_or_grandparent(goal, parent);
}
#define NULL_OR_MATCH_P(item, parent) \
((item) == NULL || parent_or_grandparent((parent), (item)))
static void audit_map(const tal_t *ctx, const struct wally_map *map)
{
assert(NULL_OR_MATCH_P(map->items, ctx));
for (size_t i = 0; i < map->num_items; i++) {
assert(NULL_OR_MATCH_P(map->items[i].key, ctx));
assert(NULL_OR_MATCH_P(map->items[i].value, ctx));
assert(!map->items[i].key
|| tal_bytelen(map->items[i].key)
== map->items[i].key_len);
assert(!map->items[i].value
|| tal_bytelen(map->items[i].value)
== map->items[i].value_len);
}
}
void audit_psbt(const tal_t *ctx, const struct wally_psbt *psbt)
{
assert(psbt);
assert(NULL_OR_MATCH_P(psbt->tx, ctx));
assert(NULL_OR_MATCH_P(psbt->inputs, ctx));
assert(NULL_OR_MATCH_P(psbt->outputs, ctx));
audit_map(ctx, &psbt->unknowns);
audit_map(ctx, &psbt->global_xpubs);
#ifndef WALLY_ABI_NO_ELEMENTS
audit_map(ctx, &psbt->global_scalars);
#endif
for (size_t i = 0; i < psbt->num_inputs; i++) {
assert(NULL_OR_MATCH_P(psbt->inputs[i].utxo, ctx));
assert(NULL_OR_MATCH_P(psbt->inputs[i].witness_utxo, ctx));
assert(NULL_OR_MATCH_P(psbt->inputs[i].final_witness, ctx));
audit_map(ctx, &psbt->inputs[i].keypaths);
audit_map(ctx, &psbt->inputs[i].signatures);
audit_map(ctx, &psbt->inputs[i].unknowns);
audit_map(ctx, &psbt->inputs[i].preimages);
audit_map(ctx, &psbt->inputs[i].psbt_fields);
audit_map(ctx, &psbt->inputs[i].taproot_leaf_signatures);
audit_map(ctx, &psbt->inputs[i].taproot_leaf_scripts);
audit_map(ctx, &psbt->inputs[i].taproot_leaf_hashes);
audit_map(ctx, &psbt->inputs[i].taproot_leaf_paths);
/* DTODO: Investigate if taproot wally maps have child maps */
#ifndef WALLY_ABI_NO_ELEMENTS
assert(NULL_OR_MATCH_P(psbt->inputs[i].pegin_tx, ctx));
assert(NULL_OR_MATCH_P(psbt->inputs[i].pegin_witness, ctx));
audit_map(ctx, &psbt->inputs[i].pset_fields);
#endif
}
for (size_t i = 0; i < psbt->num_outputs; i++) {
assert(NULL_OR_MATCH_P(psbt->outputs[i].script, ctx));
assert(psbt->outputs[i].script_len
== tal_bytelen(psbt->outputs[i].script));
audit_map(ctx, &psbt->outputs[i].keypaths);
audit_map(ctx, &psbt->outputs[i].unknowns);
audit_map(ctx, &psbt->outputs[i].psbt_fields);
audit_map(ctx, &psbt->outputs[i].taproot_tree);
audit_map(ctx, &psbt->outputs[i].taproot_leaf_hashes);
audit_map(ctx, &psbt->outputs[i].taproot_leaf_paths);
#ifndef WALLY_ABI_NO_ELEMENTS
audit_map(ctx, &psbt->outputs[i].pset_fields);
#endif
}
}
bool psbt_is_finalized(const struct wally_psbt *psbt)
{
size_t is_finalized;
@ -311,6 +384,36 @@ bool psbt_input_have_signature(const struct wally_psbt *psbt,
return ok;
}
bool psbt_input_get_ecdsa_sig(const tal_t *ctx,
const struct wally_psbt *psbt,
size_t in,
const struct pubkey *pubkey,
struct bitcoin_signature **sig)
{
u8 pk_der[PUBKEY_CMPR_LEN];
size_t index_plus_one;
struct wally_map_item *item;
bool ok;
assert(in < psbt->num_inputs);
pubkey_to_der(pk_der, pubkey);
*sig = NULL;
ok = wally_psbt_input_find_signature(&psbt->inputs[in], pk_der,
sizeof(pk_der),
&index_plus_one) == WALLY_OK;
if (ok) {
item = &psbt->inputs[in].signatures.items[index_plus_one - 1];
*sig = tal(ctx, struct bitcoin_signature);
if (!signature_from_der(item->value, item->value_len, *sig)) {
*sig = tal_free(*sig);
return false;
}
}
return ok;
}
void psbt_input_set_wit_utxo(struct wally_psbt *psbt, size_t in,
const u8 *scriptPubkey, struct amount_sat amt)
{
@ -449,10 +552,9 @@ void psbt_elements_normalize_fees(struct wally_psbt *psbt)
}
void wally_psbt_input_get_txid(const struct wally_psbt_input *in,
struct bitcoin_txid *txid)
struct bitcoin_txid *txid)
{
BUILD_ASSERT(sizeof(struct bitcoin_txid) == sizeof(in->txhash));
memcpy(txid, in->txhash, sizeof(struct bitcoin_txid));
CROSS_TYPE_ASSIGNMENT(txid, &in->txhash);
}
bool psbt_has_input(const struct wally_psbt *psbt,
@ -612,6 +714,17 @@ void *psbt_get_lightning(const struct wally_map *map,
return item->value;
}
void psbt_set_lightning(const tal_t *ctx,
struct wally_map *map,
const u8 proprietary_type,
const void *value,
size_t val_len)
{
u8 *key = psbt_make_key(NULL, proprietary_type, NULL);
map_replace(ctx, map, key, value, val_len);
tal_free(key);
}
void psbt_output_set_unknown(const tal_t *ctx,
struct wally_psbt_output *out,
const u8 *key,
@ -721,10 +834,9 @@ struct wally_psbt *psbt_from_b64(const tal_t *ctx,
size_t b64len)
{
struct wally_psbt *psbt;
char *str = tal_strndup(tmpctx, b64, b64len);
tal_wally_start();
if (wally_psbt_from_base64(str, /* flags */ 0, &psbt) == WALLY_OK)
if (wally_psbt_from_base64_n(b64, b64len, /* flags */ 0, &psbt) == WALLY_OK)
tal_add_destructor(psbt, psbt_destroy);
else
psbt = NULL;
@ -886,25 +998,21 @@ struct amount_sat psbt_compute_fee(const struct wally_psbt *psbt)
}
bool wally_psbt_input_spends(const struct wally_psbt_input *input,
const struct bitcoin_outpoint *outpoint)
const struct bitcoin_outpoint *outpoint)
{
/* Useful, as tx_part can have some NULL inputs */
if (!input)
return false;
BUILD_ASSERT(sizeof(outpoint->txid) == sizeof(input->txhash));
/* Useful, as tx_part can have some NULL inputs */
if (!input)
return false;
if (input->index != outpoint->n)
return false;
if (memcmp(&outpoint->txid, input->txhash, sizeof(outpoint->txid)) != 0)
return false;
return true;
return CROSS_TYPE_EQ(&outpoint->txid, &input->txhash);
}
void wally_psbt_input_get_outpoint(const struct wally_psbt_input *in,
struct bitcoin_outpoint *outpoint)
struct bitcoin_outpoint *outpoint)
{
BUILD_ASSERT(sizeof(struct bitcoin_txid) == sizeof(in->txhash));
memcpy(&outpoint->txid, in->txhash, sizeof(struct bitcoin_txid));
outpoint->n = in->index;
CROSS_TYPE_ASSIGNMENT(&outpoint->txid, &in->txhash);
outpoint->n = in->index;
}
const u8 *wally_psbt_output_get_script(const tal_t *ctx,

View File

@ -61,6 +61,17 @@ struct wally_psbt *combine_psbt(const tal_t *ctx,
const struct wally_psbt *psbt0,
const struct wally_psbt *psbt1);
/**
* audit_psbt - Audit the memory structure of the PSBT.
*
* This checks all known memory allocations in the PSBT and asserts that they
* are all allocated with 'ctx' being it's parent.
*
* ctx - the ctx all memory *should* be attached to
* psbt - the PSBT to audit.
* */
void audit_psbt(const tal_t *ctx, const struct wally_psbt *psbt);
/**
* psbt_is_finalized - Check if tx is ready to be extracted
*
@ -180,12 +191,20 @@ WARN_UNUSED_RESULT bool psbt_input_set_signature(struct wally_psbt *psbt, size_t
/* Returns false on error. On success, *signature_found is set to true if the
* input has a signature present for `pubkey` and false if if one was not found.
* Only ignature presence is checked, is not validated. */
* Only signature presence is checked, it is not validated. */
WARN_UNUSED_RESULT bool psbt_input_have_signature(const struct wally_psbt *psbt,
size_t in,
const struct pubkey *pubkey,
bool *signature_found);
/* Returns false on error. On success *sig is set to the signature otherwise
* *sig is set to NULL. */
WARN_UNUSED_RESULT bool psbt_input_get_ecdsa_sig(const tal_t *ctx,
const struct wally_psbt *psbt,
size_t in,
const struct pubkey *pubkey,
struct bitcoin_signature **sig);
void psbt_input_set_witscript(struct wally_psbt *psbt, size_t in, const u8 *wscript);
/* psbt_input_set_unknown - Set the given Key-Value in the psbt's input keymap
@ -212,6 +231,19 @@ void *psbt_get_lightning(const struct wally_map *map,
const u8 proprietary_type,
size_t *val_len);
/* psbt_set_lightning - Set a propreitary lightning value on the given map
*
* @map - map of unknowns to set the value
* @proprietary_type - type no. to set
* @value - the value to be set
* @val_len - length of value
*/
void psbt_set_lightning(const tal_t *ctx,
struct wally_map *map,
const u8 proprietary_type,
const void *value,
size_t val_len);
/* psbt_output_set_unknown - Set the given Key-Value in the psbt's output keymap
*
* @ctx - tal context for allocations

View File

@ -83,7 +83,7 @@ char *fmt_secp256k1_pubkey(const tal_t *ctx, const secp256k1_pubkey *key)
int pubkey_cmp(const struct pubkey *a, const struct pubkey *b)
{
u8 keya[33], keyb[33];
u8 keya[PUBKEY_CMPR_LEN], keyb[PUBKEY_CMPR_LEN];
pubkey_to_der(keya, a);
pubkey_to_der(keyb, b);
return memcmp(keya, keyb, sizeof(keya));

View File

@ -3,7 +3,6 @@
#include "config.h"
#include <ccan/compiler/compiler.h>
#include <ccan/short_types/short_types.h>
#include <ccan/structeq/structeq.h>
#include <ccan/tal/tal.h>
#include <common/gossip_constants.h>
@ -19,6 +18,12 @@ static inline bool short_channel_id_eq(struct short_channel_id a,
return a.u64 == b.u64;
}
static inline size_t short_channel_id_hash(struct short_channel_id scid)
{
/* scids cost money to generate, so simple hash works here */
return (scid.u64 >> 32) ^ (scid.u64 >> 16) ^ scid.u64;
}
/* BOLT #7:
*
* - MUST set `node_id_1` and `node_id_2` to the public keys of the two nodes
@ -36,6 +41,12 @@ struct short_channel_id_dir {
int dir;
};
static inline bool short_channel_id_dir_eq(const struct short_channel_id_dir *a,
const struct short_channel_id_dir *b)
{
return short_channel_id_eq(a->scid, b->scid) && a->dir == b->dir;
}
static inline u32 short_channel_id_blocknum(struct short_channel_id scid)
{
return scid.u64 >> 40;

View File

@ -65,6 +65,9 @@ u8 *scriptpubkey_p2wsh(const tal_t *ctx UNNEEDED, const u8 *witnessscript UNNEED
/* Generated stub for sha256_double */
void sha256_double(struct sha256_double *shadouble UNNEEDED, const void *p UNNEEDED, size_t len UNNEEDED)
{ fprintf(stderr, "sha256_double called!\n"); abort(); }
/* Generated stub for signature_from_der */
bool signature_from_der(const u8 *der UNNEEDED, size_t len UNNEEDED, struct bitcoin_signature *sig UNNEEDED)
{ fprintf(stderr, "signature_from_der called!\n"); abort(); }
/* Generated stub for signature_to_der */
size_t signature_to_der(u8 der[73] UNNEEDED, const struct bitcoin_signature *sig UNNEEDED)
{ fprintf(stderr, "signature_to_der called!\n"); abort(); }
@ -111,6 +114,7 @@ int main(int argc, char *argv[])
const struct wally_map_item *final_scriptsig = wally_map_get_integer(&tx2->psbt->inputs[0].psbt_fields, /* PSBT_IN_FINAL_SCRIPTSIG */ 0x07);
assert(final_scriptsig->value_len > 0);
assert(tx2->psbt->inputs[0].final_witness != NULL);
audit_psbt(tx2->psbt, tx2->psbt);
common_shutdown();
return 0;

View File

@ -403,8 +403,7 @@ void bitcoin_tx_input_set_outpoint(struct bitcoin_tx *tx, int innum,
assert(innum < tx->wtx->num_inputs);
in = &tx->wtx->inputs[innum];
BUILD_ASSERT(sizeof(struct bitcoin_txid) == sizeof(in->txhash));
memcpy(in->txhash, &outpoint->txid, sizeof(struct bitcoin_txid));
CROSS_TYPE_ASSIGNMENT(&in->txhash, &outpoint->txid);
in->index = outpoint->n;
}
@ -412,15 +411,13 @@ void bitcoin_tx_input_set_outpoint(struct bitcoin_tx *tx, int innum,
void wally_tx_input_get_txid(const struct wally_tx_input *in,
struct bitcoin_txid *txid)
{
BUILD_ASSERT(sizeof(struct bitcoin_txid) == sizeof(in->txhash));
memcpy(txid, in->txhash, sizeof(struct bitcoin_txid));
CROSS_TYPE_ASSIGNMENT(txid, &in->txhash);
}
void wally_tx_input_get_outpoint(const struct wally_tx_input *in,
struct bitcoin_outpoint *outpoint)
{
BUILD_ASSERT(sizeof(struct bitcoin_txid) == sizeof(in->txhash));
memcpy(&outpoint->txid, in->txhash, sizeof(struct bitcoin_txid));
wally_tx_input_get_txid(in, &outpoint->txid);
outpoint->n = in->index;
}
@ -551,9 +548,13 @@ void bitcoin_tx_finalize(struct bitcoin_tx *tx)
assert(bitcoin_tx_check(tx));
}
struct bitcoin_tx *bitcoin_tx_with_psbt(const tal_t *ctx, struct wally_psbt *psbt STEALS)
struct bitcoin_tx *bitcoin_tx_with_psbt(const tal_t *ctx, struct wally_psbt *psbt TAKES)
{
size_t locktime;
if (!taken(psbt))
psbt = clone_psbt(tmpctx, psbt);
wally_psbt_get_locktime(psbt, &locktime);
struct bitcoin_tx *tx = bitcoin_tx(ctx, chainparams,
psbt->num_inputs,
@ -693,18 +694,6 @@ fail:
return NULL;
}
/* <sigh>. Bitcoind represents hashes as little-endian for RPC. */
static void reverse_bytes(u8 *arr, size_t len)
{
unsigned int i;
for (i = 0; i < len / 2; i++) {
unsigned char tmp = arr[i];
arr[i] = arr[len - 1 - i];
arr[len - 1 - i] = tmp;
}
}
bool bitcoin_txid_from_hex(const char *hexstr, size_t hexstr_len,
struct bitcoin_txid *txid)
{
@ -824,8 +813,7 @@ bool wally_tx_input_spends(const struct wally_tx_input *input,
/* Useful, as tx_part can have some NULL inputs */
if (!input)
return false;
BUILD_ASSERT(sizeof(outpoint->txid) == sizeof(input->txhash));
if (memcmp(&outpoint->txid, input->txhash, sizeof(outpoint->txid)) != 0)
if (!CROSS_TYPE_EQ(&outpoint->txid, &input->txhash))
return false;
return input->index == outpoint->n;
}
@ -909,7 +897,8 @@ size_t bitcoin_tx_input_sig_weight(void)
/* Input weight */
size_t bitcoin_tx_input_weight(bool p2sh, size_t witness_weight)
{
size_t weight = witness_weight;
/* We assume < 253 witness elements */
size_t weight = 1 + witness_weight;
/* Input weight: txid + index + sequence */
weight += (32 + 4 + 4) * 4;
@ -928,17 +917,32 @@ size_t bitcoin_tx_input_weight(bool p2sh, size_t witness_weight)
return weight;
}
size_t bitcoin_tx_simple_input_witness_weight(void)
size_t bitcoin_tx_input_witness_weight(enum utxotype utxotype)
{
/* Account for witness (1 byte count + sig + key) */
return 1 + (bitcoin_tx_input_sig_weight() + 1 + 33);
}
/* We only do segwit inputs, and we assume witness is sig + key */
size_t bitcoin_tx_simple_input_weight(bool p2sh)
{
return bitcoin_tx_input_weight(p2sh,
bitcoin_tx_simple_input_witness_weight());
switch (utxotype) {
case UTXO_P2SH_P2WPKH:
case UTXO_P2WPKH:
/* Account for witness (sig + key) */
return bitcoin_tx_input_sig_weight() + 1 + 33;
case UTXO_P2WSH_FROM_CLOSE:
/* BOLT #3:
* #### `to_remote` Output
*
* If `option_anchors` applies to the commitment
* transaction, the `to_remote` output is encumbered by a one
* block csv lock.
* <remotepubkey> OP_CHECKSIGVERIFY 1 OP_CHECKSEQUENCEVERIFY
*
* The output is spent by an input with `nSequence` field set
* to `1` and witness: <remote_sig>
* Otherwise, this output is a simple P2WPKH to `remotepubkey`.
*/
/* In practice, these predate anchors, so: */
return 1 + 1 + bitcoin_tx_input_sig_weight();
case UTXO_P2TR:
return 1 + 64;
}
abort();
}
size_t bitcoin_tx_2of2_input_witness_weight(void)

View File

@ -48,6 +48,17 @@ struct bitcoin_tx_output {
u8 *script;
};
enum utxotype {
/* Obsolete: we used to have P2SH-wrapped outputs (removed in 24.02, though can still have old UTXOs) */
UTXO_P2SH_P2WPKH = 1,
/* "bech32" addresses */
UTXO_P2WPKH = 2,
/* Used for closing addresses: implies ->close_info is non-NULL */
UTXO_P2WSH_FROM_CLOSE = 3,
/* "p2tr" addresses. */
UTXO_P2TR = 4,
};
struct bitcoin_tx_output *new_tx_output(const tal_t *ctx,
struct amount_sat amount,
const u8 *script);
@ -79,6 +90,18 @@ struct bitcoin_tx *clone_bitcoin_tx(const tal_t *ctx,
struct bitcoin_tx *bitcoin_tx_from_hex(const tal_t *ctx, const char *hex,
size_t hexlen);
/* <sigh>. Bitcoind represents hashes as little-endian for RPC. */
static inline void reverse_bytes(u8 *arr, size_t len)
{
unsigned int i;
for (i = 0; i < len / 2; i++) {
unsigned char tmp = arr[i];
arr[i] = arr[len - 1 - i];
arr[len - 1 - i] = tmp;
}
}
/* Parse hex string to get txid (reversed, a-la bitcoind). */
bool bitcoin_txid_from_hex(const char *hexstr, size_t hexstr_len,
struct bitcoin_txid *txid);
@ -88,7 +111,8 @@ bool bitcoin_txid_to_hex(const struct bitcoin_txid *txid,
char *hexstr, size_t hexstr_len);
/* Create a bitcoin_tx from a psbt */
struct bitcoin_tx *bitcoin_tx_with_psbt(const tal_t *ctx, struct wally_psbt *psbt);
struct bitcoin_tx *bitcoin_tx_with_psbt(const tal_t *ctx,
struct wally_psbt *psbt TAKES);
/* Internal de-linearization functions. */
/* Pull a bitcoin tx, and create a PSBT wrapper for it */
@ -303,14 +327,13 @@ size_t bitcoin_tx_output_weight(size_t outscript_len);
/* Weight to push sig on stack. */
size_t bitcoin_tx_input_sig_weight(void);
/* Segwit input, but with parameter for witness weight (size) */
/* Segwit input, but with parameter for witness weight (size).
* witness_weight must include the varint_size() for each witness element,
* but not the varint_size() for the number of elements. */
size_t bitcoin_tx_input_weight(bool p2sh, size_t witness_weight);
/* The witness weight for a simple (sig + key) input */
size_t bitcoin_tx_simple_input_witness_weight(void);
/* We only do segwit inputs, and we assume witness is sig + key */
size_t bitcoin_tx_simple_input_weight(bool p2sh);
/* The witness weight */
size_t bitcoin_tx_input_witness_weight(enum utxotype utxotype);
/* The witness for our 2of2 input (closing or commitment tx). */
size_t bitcoin_tx_2of2_input_witness_weight(void);

View File

@ -1,3 +1,3 @@
CCAN imported from http://ccodearchive.net.
CCAN version: init-2578-g29e55f74
CCAN version: init-2593-gca094039

View File

@ -9,7 +9,7 @@
#define BIT_ALIGN_DOWN(n) ((n) & ~(BITMAP_WORD_BITS - 1))
#define BIT_ALIGN_UP(n) BIT_ALIGN_DOWN((n) + BITMAP_WORD_BITS - 1)
void bitmap_zero_range(bitmap *bitmap, unsigned long n, unsigned long m)
void bitmap_zero_range(bitmap *b, unsigned long n, unsigned long m)
{
unsigned long an = BIT_ALIGN_UP(n);
unsigned long am = BIT_ALIGN_DOWN(m);
@ -19,22 +19,22 @@ void bitmap_zero_range(bitmap *bitmap, unsigned long n, unsigned long m)
assert(m >= n);
if (am < an) {
BITMAP_WORD(bitmap, n) &= ~bitmap_bswap(headmask & tailmask);
BITMAP_WORD(b, n) &= ~bitmap_bswap(headmask & tailmask);
return;
}
if (an > n)
BITMAP_WORD(bitmap, n) &= ~bitmap_bswap(headmask);
BITMAP_WORD(b, n) &= ~bitmap_bswap(headmask);
if (am > an)
memset(&BITMAP_WORD(bitmap, an), 0,
memset(&BITMAP_WORD(b, an), 0,
(am - an) / BITMAP_WORD_BITS * sizeof(bitmap_word));
if (m > am)
BITMAP_WORD(bitmap, m) &= ~bitmap_bswap(tailmask);
BITMAP_WORD(b, m) &= ~bitmap_bswap(tailmask);
}
void bitmap_fill_range(bitmap *bitmap, unsigned long n, unsigned long m)
void bitmap_fill_range(bitmap *b, unsigned long n, unsigned long m)
{
unsigned long an = BIT_ALIGN_UP(n);
unsigned long am = BIT_ALIGN_DOWN(m);
@ -44,19 +44,19 @@ void bitmap_fill_range(bitmap *bitmap, unsigned long n, unsigned long m)
assert(m >= n);
if (am < an) {
BITMAP_WORD(bitmap, n) |= bitmap_bswap(headmask & tailmask);
BITMAP_WORD(b, n) |= bitmap_bswap(headmask & tailmask);
return;
}
if (an > n)
BITMAP_WORD(bitmap, n) |= bitmap_bswap(headmask);
BITMAP_WORD(b, n) |= bitmap_bswap(headmask);
if (am > an)
memset(&BITMAP_WORD(bitmap, an), 0xff,
memset(&BITMAP_WORD(b, an), 0xff,
(am - an) / BITMAP_WORD_BITS * sizeof(bitmap_word));
if (m > am)
BITMAP_WORD(bitmap, m) |= bitmap_bswap(tailmask);
BITMAP_WORD(b, m) |= bitmap_bswap(tailmask);
}
static int bitmap_clz(bitmap_word w)
@ -76,7 +76,7 @@ static int bitmap_clz(bitmap_word w)
#endif
}
unsigned long bitmap_ffs(const bitmap *bitmap,
unsigned long bitmap_ffs(const bitmap *b,
unsigned long n, unsigned long m)
{
unsigned long an = BIT_ALIGN_UP(n);
@ -87,7 +87,7 @@ unsigned long bitmap_ffs(const bitmap *bitmap,
assert(m >= n);
if (am < an) {
bitmap_word w = bitmap_bswap(BITMAP_WORD(bitmap, n));
bitmap_word w = bitmap_bswap(BITMAP_WORD(b, n));
w &= (headmask & tailmask);
@ -95,7 +95,7 @@ unsigned long bitmap_ffs(const bitmap *bitmap,
}
if (an > n) {
bitmap_word w = bitmap_bswap(BITMAP_WORD(bitmap, n));
bitmap_word w = bitmap_bswap(BITMAP_WORD(b, n));
w &= headmask;
@ -104,7 +104,7 @@ unsigned long bitmap_ffs(const bitmap *bitmap,
}
while (an < am) {
bitmap_word w = bitmap_bswap(BITMAP_WORD(bitmap, an));
bitmap_word w = bitmap_bswap(BITMAP_WORD(b, an));
if (w)
return an + bitmap_clz(w);
@ -113,7 +113,7 @@ unsigned long bitmap_ffs(const bitmap *bitmap,
}
if (m > am) {
bitmap_word w = bitmap_bswap(BITMAP_WORD(bitmap, m));
bitmap_word w = bitmap_bswap(BITMAP_WORD(b, m));
w &= tailmask;

View File

@ -58,37 +58,37 @@ static inline bitmap_word bitmap_bswap(bitmap_word w)
#define BITMAP_TAIL(_bm, _nbits) \
(BITMAP_TAILWORD(_bm, _nbits) & BITMAP_TAILBITS(_nbits))
static inline void bitmap_set_bit(bitmap *bitmap, unsigned long n)
static inline void bitmap_set_bit(bitmap *b, unsigned long n)
{
BITMAP_WORD(bitmap, n) |= BITMAP_WORDBIT(n);
BITMAP_WORD(b, n) |= BITMAP_WORDBIT(n);
}
static inline void bitmap_clear_bit(bitmap *bitmap, unsigned long n)
static inline void bitmap_clear_bit(bitmap *b, unsigned long n)
{
BITMAP_WORD(bitmap, n) &= ~BITMAP_WORDBIT(n);
BITMAP_WORD(b, n) &= ~BITMAP_WORDBIT(n);
}
static inline void bitmap_change_bit(bitmap *bitmap, unsigned long n)
static inline void bitmap_change_bit(bitmap *b, unsigned long n)
{
BITMAP_WORD(bitmap, n) ^= BITMAP_WORDBIT(n);
BITMAP_WORD(b, n) ^= BITMAP_WORDBIT(n);
}
static inline bool bitmap_test_bit(const bitmap *bitmap, unsigned long n)
static inline bool bitmap_test_bit(const bitmap *b, unsigned long n)
{
return !!(BITMAP_WORD(bitmap, n) & BITMAP_WORDBIT(n));
return !!(BITMAP_WORD(b, n) & BITMAP_WORDBIT(n));
}
void bitmap_zero_range(bitmap *bitmap, unsigned long n, unsigned long m);
void bitmap_fill_range(bitmap *bitmap, unsigned long n, unsigned long m);
void bitmap_zero_range(bitmap *b, unsigned long n, unsigned long m);
void bitmap_fill_range(bitmap *b, unsigned long n, unsigned long m);
static inline void bitmap_zero(bitmap *bitmap, unsigned long nbits)
static inline void bitmap_zero(bitmap *b, unsigned long nbits)
{
memset(bitmap, 0, bitmap_sizeof(nbits));
memset(b, 0, bitmap_sizeof(nbits));
}
static inline void bitmap_fill(bitmap *bitmap, unsigned long nbits)
static inline void bitmap_fill(bitmap *b, unsigned long nbits)
{
memset(bitmap, 0xff, bitmap_sizeof(nbits));
memset(b, 0xff, bitmap_sizeof(nbits));
}
static inline void bitmap_copy(bitmap *dst, const bitmap *src,
@ -161,37 +161,36 @@ static inline bool bitmap_subset(const bitmap *src1, const bitmap *src2,
return true;
}
static inline bool bitmap_full(const bitmap *bitmap, unsigned long nbits)
static inline bool bitmap_full(const bitmap *b, unsigned long nbits)
{
unsigned long i;
for (i = 0; i < BITMAP_HEADWORDS(nbits); i++) {
if (bitmap[i].w != -1UL)
if (b[i].w != -1UL)
return false;
}
if (BITMAP_HASTAIL(nbits) &&
(BITMAP_TAIL(bitmap, nbits) != BITMAP_TAILBITS(nbits)))
(BITMAP_TAIL(b, nbits) != BITMAP_TAILBITS(nbits)))
return false;
return true;
}
static inline bool bitmap_empty(const bitmap *bitmap, unsigned long nbits)
static inline bool bitmap_empty(const bitmap *b, unsigned long nbits)
{
unsigned long i;
for (i = 0; i < BITMAP_HEADWORDS(nbits); i++) {
if (bitmap[i].w != 0)
if (b[i].w != 0)
return false;
}
if (BITMAP_HASTAIL(nbits) && (BITMAP_TAIL(bitmap, nbits) != 0))
if (BITMAP_HASTAIL(nbits) && (BITMAP_TAIL(b, nbits) != 0))
return false;
return true;
}
unsigned long bitmap_ffs(const bitmap *bitmap,
unsigned long n, unsigned long m);
unsigned long bitmap_ffs(const bitmap *b, unsigned long n, unsigned long m);
/*
* Allocation functions
@ -221,26 +220,26 @@ static inline bitmap *bitmap_alloc1(unsigned long nbits)
return bitmap;
}
static inline bitmap *bitmap_realloc0(bitmap *bitmap,
static inline bitmap *bitmap_realloc0(bitmap *b,
unsigned long obits, unsigned long nbits)
{
bitmap = realloc(bitmap, bitmap_sizeof(nbits));
b = realloc(b, bitmap_sizeof(nbits));
if ((nbits > obits) && bitmap)
bitmap_zero_range(bitmap, obits, nbits);
if ((nbits > obits) && b)
bitmap_zero_range(b, obits, nbits);
return bitmap;
return b;
}
static inline bitmap *bitmap_realloc1(bitmap *bitmap,
static inline bitmap *bitmap_realloc1(bitmap *b,
unsigned long obits, unsigned long nbits)
{
bitmap = realloc(bitmap, bitmap_sizeof(nbits));
b = realloc(b, bitmap_sizeof(nbits));
if ((nbits > obits) && bitmap)
bitmap_fill_range(bitmap, obits, nbits);
if ((nbits > obits) && b)
bitmap_fill_range(b, obits, nbits);
return bitmap;
return b;
}
#endif /* CCAN_BITMAP_H_ */

View File

@ -80,7 +80,7 @@ void siphash24_init(struct siphash24_ctx *ctx, const struct siphash_seed *seed);
* SIPHASH24_INIT - initializer for an SIPHASH24 context.
* @seed1, @seed2: two 64-bit words for seed.
*
* This can be used to statically initialize an SIPHASH24 context (instead
* This can be used to staticly initialize an SIPHASH24 context (instead
* of siphash24_init()).
*
* Example:

View File

@ -3,6 +3,7 @@
#include <sys/socket.h>
#include <errno.h>
#include <string.h>
#include <sys/types.h>
bool fdpass_send(int sockout, int fd)
{

View File

@ -1,19 +1,23 @@
/* Licensed under LGPLv2+ - see LICENSE file for details */
#ifndef CCAN_HTABLE_TYPE_H
#define CCAN_HTABLE_TYPE_H
#include "config.h"
#include <assert.h>
#include <ccan/htable/htable.h>
#include <ccan/compiler/compiler.h>
#include "config.h"
/**
* HTABLE_DEFINE_TYPE - create a set of htable ops for a type
* HTABLE_DEFINE_NODUPS_TYPE/HTABLE_DEFINE_DUPS_TYPE - create a set of htable ops for a type
* @type: a type whose pointers will be values in the hash.
* @keyof: a function/macro to extract a key: <keytype> @keyof(const type *elem)
* @hashfn: a hash function for a @key: size_t @hashfn(const <keytype> *)
* @eqfn: an equality function keys: bool @eqfn(const type *, const <keytype> *)
* @prefix: a prefix for all the functions to define (of form <name>_*)
*
* NULL values may not be placed into the hash table.
* There are two variants, one of which allows duplicate keys, and one which
* does not. The defined functions differ in some cases, as shown below.
*
* NULL values may not be placed into the hash table (nor (void *)1).
*
* This defines the type hashtable type and an iterator type:
* struct <name>;
@ -33,15 +37,18 @@
*
* Delete and delete-by key return true if it was in the set:
* bool <name>_del(struct <name> *ht, const <type> *e);
* bool <name>_delkey(struct <name> *ht, const <keytype> *k);
* bool <name>_delkey(struct <name> *ht, const <keytype> *k) (NODUPS only);
*
* Delete by iterator:
* bool <name>_delval(struct <name> *ht, struct <name>_iter *i);
*
* Find and return the (first) matching element, or NULL:
* type *<name>_get(const struct @name *ht, const <keytype> *k);
* Find and return the matching element, or NULL:
* type *<name>_get(const struct @name *ht, const <keytype> *k) (NODUPS only);
*
* Find and return all matching elements, or NULL:
* Test for an element:
* bool <name>_exists(const struct @name *ht, const <keytype> *k);
*
* Find and return all matching elements, or NULL (DUPS only):
* type *<name>_getfirst(const struct @name *ht, const <keytype> *k,
* struct <name>_iter *i);
* type *<name>_getnext(const struct @name *ht, const <keytype> *k,
@ -59,7 +66,7 @@
* You can use HTABLE_INITIALIZER like so:
* struct <name> ht = { HTABLE_INITIALIZER(ht.raw, <name>_hash, NULL) };
*/
#define HTABLE_DEFINE_TYPE(type, keyof, hashfn, eqfn, name) \
#define HTABLE_DEFINE_TYPE_CORE(type, keyof, hashfn, eqfn, name) \
struct name { struct htable raw; }; \
struct name##_iter { struct htable_iter i; }; \
static inline size_t name##_hash(const void *elem, void *priv) \
@ -89,66 +96,33 @@
{ \
return htable_copy(&dst->raw, &src->raw); \
} \
static inline bool name##_add(struct name *ht, const type *elem) \
{ \
return htable_add(&ht->raw, hashfn(keyof(elem)), elem); \
} \
static inline UNNEEDED bool name##_del(struct name *ht, \
const type *elem) \
{ \
return htable_del(&ht->raw, hashfn(keyof(elem)), elem); \
} \
static inline UNNEEDED type *name##_get(const struct name *ht, \
const HTABLE_KTYPE(keyof, type) k) \
{ \
struct htable_iter i; \
size_t h = hashfn(k); \
void *c; \
\
for (c = htable_firstval(&ht->raw,&i,h); \
c; \
c = htable_nextval(&ht->raw,&i,h)) { \
if (eqfn(c, k)) \
return c; \
} \
return NULL; \
} \
static inline UNNEEDED type *name##_getmatch_(const struct name *ht, \
const HTABLE_KTYPE(keyof, type) k, \
size_t h, \
type *v, \
struct name##_iter *iter) \
struct htable_iter *iter) \
{ \
while (v) { \
if (eqfn(v, k)) \
break; \
v = htable_nextval(&ht->raw, &iter->i, h); \
v = htable_nextval(&ht->raw, iter, h); \
} \
return v; \
} \
static inline UNNEEDED type *name##_getfirst(const struct name *ht, \
const HTABLE_KTYPE(keyof, type) k, \
struct name##_iter *iter) \
static inline UNNEEDED bool name##_exists(const struct name *ht, \
const HTABLE_KTYPE(keyof, type) k) \
{ \
struct htable_iter i; \
size_t h = hashfn(k); \
type *v = htable_firstval(&ht->raw, &iter->i, h); \
return name##_getmatch_(ht, k, h, v, iter); \
} \
static inline UNNEEDED type *name##_getnext(const struct name *ht, \
const HTABLE_KTYPE(keyof, type) k, \
struct name##_iter *iter) \
{ \
size_t h = hashfn(k); \
type *v = htable_nextval(&ht->raw, &iter->i, h); \
return name##_getmatch_(ht, k, h, v, iter); \
} \
static inline UNNEEDED bool name##_delkey(struct name *ht, \
const HTABLE_KTYPE(keyof, type) k) \
{ \
type *elem = name##_get(ht, k); \
if (elem) \
return name##_del(ht, elem); \
return false; \
void *v; \
\
v = htable_firstval(&ht->raw, &i, h); \
return name##_getmatch_(ht, k, h, v, &i) != NULL; \
} \
static inline UNNEEDED void name##_delval(struct name *ht, \
struct name##_iter *iter) \
@ -177,6 +151,64 @@
return htable_prev(&ht->raw, &iter->i); \
}
#define HTABLE_DEFINE_NODUPS_TYPE(type, keyof, hashfn, eqfn, name) \
HTABLE_DEFINE_TYPE_CORE(type, keyof, hashfn, eqfn, name) \
static inline UNNEEDED type *name##_get(const struct name *ht, \
const HTABLE_KTYPE(keyof, type) k) \
{ \
struct htable_iter i; \
size_t h = hashfn(k); \
void *v; \
\
v = htable_firstval(&ht->raw, &i, h); \
return name##_getmatch_(ht, k, h, v, &i); \
} \
static inline bool name##_add(struct name *ht, const type *elem) \
{ \
/* Open-coded for slightly more efficiency */ \
const HTABLE_KTYPE(keyof, type) k = keyof(elem); \
struct htable_iter i; \
size_t h = hashfn(k); \
void *v; \
\
v = htable_firstval(&ht->raw, &i, h); \
assert(!name##_getmatch_(ht, k, h, v, &i)); \
return htable_add(&ht->raw, h, elem); \
} \
static inline UNNEEDED bool name##_delkey(struct name *ht, \
const HTABLE_KTYPE(keyof, type) k) \
{ \
type *elem = name##_get(ht, k); \
if (elem) \
return name##_del(ht, elem); \
return false; \
}
#define HTABLE_DEFINE_DUPS_TYPE(type, keyof, hashfn, eqfn, name) \
HTABLE_DEFINE_TYPE_CORE(type, keyof, hashfn, eqfn, name) \
static inline bool name##_add(struct name *ht, const type *elem) \
{ \
const HTABLE_KTYPE(keyof, type) k = keyof(elem); \
return htable_add(&ht->raw, hashfn(k), elem); \
} \
static inline UNNEEDED type *name##_getfirst(const struct name *ht, \
const HTABLE_KTYPE(keyof, type) k, \
struct name##_iter *iter) \
{ \
size_t h = hashfn(k); \
type *v = htable_firstval(&ht->raw, &iter->i, h); \
return name##_getmatch_(ht, k, h, v, &iter->i); \
} \
static inline UNNEEDED type *name##_getnext(const struct name *ht, \
const HTABLE_KTYPE(keyof, type) k, \
struct name##_iter *iter) \
{ \
size_t h = hashfn(k); \
type *v = htable_nextval(&ht->raw, &iter->i, h); \
return name##_getmatch_(ht, k, h, v, &iter->i); \
}
#if HAVE_TYPEOF
#define HTABLE_KTYPE(keyof, type) typeof(keyof((const type *)NULL))
#else

View File

@ -38,7 +38,7 @@ static bool cmp(const struct obj *obj, const unsigned int key)
return obj->key == key;
}
HTABLE_DEFINE_TYPE(struct obj, objkey, objhash, cmp, htable_obj);
HTABLE_DEFINE_NODUPS_TYPE(struct obj, objkey, objhash, cmp, htable_obj);
static void add_vals(struct htable_obj *ht,
struct obj val[], unsigned int num)
@ -112,14 +112,19 @@ static bool check_mask(struct htable *ht, const struct obj val[], unsigned num)
return true;
}
/* This variant allows duplicates! */
HTABLE_DEFINE_DUPS_TYPE(struct obj, objkey, objhash, cmp, htable_obj_dups);
int main(void)
{
unsigned int i;
struct htable_obj ht, ht2;
struct htable_obj_dups ht_dups;
struct obj val[NUM_VALS], *result;
unsigned int dne;
void *p;
struct htable_obj_iter iter;
struct htable_obj_dups_iter dups_iter;
plan_tests(29);
for (i = 0; i < NUM_VALS; i++)
@ -183,32 +188,35 @@ int main(void)
del_vals_bykey(&ht, val, NUM_VALS);
del_vals_bykey(&ht2, val, NUM_VALS);
/* Duplicates-allowed tests */
htable_obj_dups_init(&ht_dups);
/* Write two of the same value. */
val[1] = val[0];
htable_obj_add(&ht, &val[0]);
htable_obj_add(&ht, &val[1]);
htable_obj_dups_add(&ht_dups, &val[0]);
htable_obj_dups_add(&ht_dups, &val[1]);
i = 0;
result = htable_obj_getfirst(&ht, i, &iter);
result = htable_obj_dups_getfirst(&ht_dups, i, &dups_iter);
ok1(result == &val[0] || result == &val[1]);
if (result == &val[0]) {
ok1(htable_obj_getnext(&ht, i, &iter) == &val[1]);
ok1(htable_obj_getnext(&ht, i, &iter) == NULL);
ok1(htable_obj_dups_getnext(&ht_dups, i, &dups_iter) == &val[1]);
ok1(htable_obj_dups_getnext(&ht_dups, i, &dups_iter) == NULL);
/* Deleting first should make us iterate over the other. */
ok1(htable_obj_del(&ht, &val[0]));
ok1(htable_obj_getfirst(&ht, i, &iter) == &val[1]);
ok1(htable_obj_getnext(&ht, i, &iter) == NULL);
ok1(htable_obj_dups_del(&ht_dups, &val[0]));
ok1(htable_obj_dups_getfirst(&ht_dups, i, &dups_iter) == &val[1]);
ok1(htable_obj_dups_getnext(&ht_dups, i, &dups_iter) == NULL);
} else {
ok1(htable_obj_getnext(&ht, i, &iter) == &val[0]);
ok1(htable_obj_getnext(&ht, i, &iter) == NULL);
ok1(htable_obj_dups_getnext(&ht_dups, i, &dups_iter) == &val[0]);
ok1(htable_obj_dups_getnext(&ht_dups, i, &dups_iter) == NULL);
/* Deleting first should make us iterate over the other. */
ok1(htable_obj_del(&ht, &val[1]));
ok1(htable_obj_getfirst(&ht, i, &iter) == &val[0]);
ok1(htable_obj_getnext(&ht, i, &iter) == NULL);
ok1(htable_obj_dups_del(&ht_dups, &val[1]));
ok1(htable_obj_dups_getfirst(&ht_dups, i, &dups_iter) == &val[0]);
ok1(htable_obj_dups_getnext(&ht_dups, i, &dups_iter) == NULL);
}
htable_obj_dups_clear(&ht_dups);
htable_obj_clear(&ht);
htable_obj_clear(&ht2);
return exit_status();

View File

@ -33,7 +33,10 @@ static bool cmp(const struct obj *obj, const unsigned int *key)
return obj->key == *key;
}
HTABLE_DEFINE_TYPE(struct obj, objkey, objhash, cmp, htable_obj);
HTABLE_DEFINE_NODUPS_TYPE(struct obj, objkey, objhash, cmp,
htable_obj);
HTABLE_DEFINE_DUPS_TYPE(struct obj, objkey, objhash, cmp,
htable_obj_dups);
static void add_vals(struct htable_obj *ht,
struct obj val[], unsigned int num)
@ -111,12 +114,14 @@ int main(void)
{
unsigned int i;
struct htable_obj ht, ht2;
struct htable_obj_dups ht_dups;
struct obj val[NUM_VALS], *result;
unsigned int dne;
void *p;
struct htable_obj_iter iter;
struct htable_obj_dups_iter dups_iter;
plan_tests(35);
plan_tests(36);
for (i = 0; i < NUM_VALS; i++)
val[i].key = i;
dne = i;
@ -182,32 +187,37 @@ int main(void)
del_vals_bykey(&ht, val, NUM_VALS);
del_vals_bykey(&ht2, val, NUM_VALS);
/* Duplicates-allowed tests */
htable_obj_dups_init(&ht_dups);
/* Write two of the same value. */
val[1] = val[0];
htable_obj_add(&ht, &val[0]);
htable_obj_add(&ht, &val[1]);
htable_obj_dups_add(&ht_dups, &val[0]);
htable_obj_dups_add(&ht_dups, &val[1]);
i = 0;
result = htable_obj_getfirst(&ht, &i, &iter);
result = htable_obj_dups_getfirst(&ht_dups, &i, &dups_iter);
ok1(result == &val[0] || result == &val[1]);
if (result == &val[0]) {
ok1(htable_obj_getnext(&ht, &i, &iter) == &val[1]);
ok1(htable_obj_getnext(&ht, &i, &iter) == NULL);
ok1(htable_obj_dups_getnext(&ht_dups, &i, &dups_iter) == &val[1]);
ok1(htable_obj_dups_getnext(&ht_dups, &i, &dups_iter) == NULL);
/* Deleting first should make us iterate over the other. */
ok1(htable_obj_del(&ht, &val[0]));
ok1(htable_obj_getfirst(&ht, &i, &iter) == &val[1]);
ok1(htable_obj_getnext(&ht, &i, &iter) == NULL);
ok1(htable_obj_dups_del(&ht_dups, &val[0]));
ok1(htable_obj_dups_getfirst(&ht_dups, &i, &dups_iter) == &val[1]);
ok1(htable_obj_dups_getnext(&ht_dups, &i, &dups_iter) == NULL);
} else {
ok1(htable_obj_getnext(&ht, &i, &iter) == &val[0]);
ok1(htable_obj_getnext(&ht, &i, &iter) == NULL);
ok1(htable_obj_dups_getnext(&ht_dups, &i, &dups_iter) == &val[0]);
ok1(htable_obj_dups_getnext(&ht_dups, &i, &dups_iter) == NULL);
/* Deleting first should make us iterate over the other. */
ok1(htable_obj_del(&ht, &val[1]));
ok1(htable_obj_getfirst(&ht, &i, &iter) == &val[0]);
ok1(htable_obj_getnext(&ht, &i, &iter) == NULL);
ok1(htable_obj_dups_del(&ht_dups, &val[1]));
ok1(htable_obj_dups_getfirst(&ht_dups, &i, &dups_iter) == &val[0]);
ok1(htable_obj_dups_getnext(&ht_dups, &i, &dups_iter) == NULL);
}
htable_obj_dups_clear(&ht_dups);
ok1(htable_obj_dups_count(&ht_dups) == 0);
htable_obj_clear(&ht);
ok1(htable_obj_count(&ht) == 0);
htable_obj_clear(&ht2);

View File

@ -26,7 +26,7 @@ static bool cmp(const ptrint_t *p, uintptr_t k)
return key(p) == k;
}
HTABLE_DEFINE_TYPE(ptrint_t, key, hash_uintptr, cmp, htable_ptrint);
HTABLE_DEFINE_NODUPS_TYPE(ptrint_t, key, hash_uintptr, cmp, htable_ptrint);
/* Nanoseconds per operation */
static size_t normalize(const struct timeabs *start,

View File

@ -33,7 +33,7 @@ static bool cmp(const struct object *object, const unsigned int *key)
return object->key == *key;
}
HTABLE_DEFINE_TYPE(struct object, objkey, hash_obj, cmp, htable_obj);
HTABLE_DEFINE_NODUPS_TYPE(struct object, objkey, hash_obj, cmp, htable_obj);
static unsigned int popcount(unsigned long val)
{

View File

@ -31,7 +31,7 @@ static bool cmp(const char *obj, const char *key)
return strcmp(obj, key) == 0;
}
HTABLE_DEFINE_TYPE(char, strkey, hash_str, cmp, htable_str);
HTABLE_DEFINE_NODUPS_TYPE(char, strkey, hash_str, cmp, htable_str);
/* Nanoseconds per operation */
static size_t normalize(const struct timeabs *start,

View File

@ -59,7 +59,7 @@ static bool eqfn(const struct htable_elem *elem, const uint64_t index)
{
return elem->index == index;
}
HTABLE_DEFINE_TYPE(struct htable_elem, keyof, hashfn, eqfn, hash);
HTABLE_DEFINE_NODUPS_TYPE(struct htable_elem, keyof, hashfn, eqfn, hash);
static bool check_val(intmap_index_t i, uint64_t *v, uint64_t *expected)
{

View File

@ -1,16 +1,17 @@
ALL:=run-loop run-different-speed run-length-prefix
ALL:=run-loop run-different-speed run-length-prefix run-stream-many
CCANDIR:=../../..
CFLAGS:=-Wall -I$(CCANDIR) -O3 -flto
LDFLAGS:=-O3 -flto
LDLIBS:=-lrt
OBJS:=time.o poll.o io.o err.o timer.o list.o
OBJS:=time.o poll.o io.o err.o timer.o list.o ccan-tal.o ccan-take.o ccan-ilog.o
default: $(ALL)
run-loop: run-loop.o $(OBJS)
run-different-speed: run-different-speed.o $(OBJS)
run-length-prefix: run-length-prefix.o $(OBJS)
run-stream-many: run-stream-many.o $(OBJS)
time.o: $(CCANDIR)/ccan/time/time.c
$(CC) $(CFLAGS) -c -o $@ $<
@ -24,6 +25,12 @@ io.o: $(CCANDIR)/ccan/io/io.c
$(CC) $(CFLAGS) -c -o $@ $<
err.o: $(CCANDIR)/ccan/err/err.c
$(CC) $(CFLAGS) -c -o $@ $<
ccan-ilog.o: $(CCANDIR)/ccan/ilog/ilog.c
$(CC) $(CFLAGS) -c -o $@ $<
ccan-tal.o: $(CCANDIR)/ccan/tal/tal.c
$(CC) $(CFLAGS) -c -o $@ $<
ccan-take.o: $(CCANDIR)/ccan/take/take.c
$(CC) $(CFLAGS) -c -o $@ $<
clean:
rm -f *.o $(ALL)

View File

@ -0,0 +1,132 @@
/* Wait for many fds to connect, then try to stream the file to some of them in small chunks.
*
* This approximates the connectd behaviour in CLN, where we send gossip to peers.
*/
#include <ccan/io/io.h>
#include <ccan/ptrint/ptrint.h>
#include <ccan/time/time.h>
#include <inttypes.h>
#include <stdio.h>
#include <string.h>
#include <assert.h>
#include <err.h>
#include <signal.h>
#include <sys/socket.h>
#include <netinet/in.h>
/* We expect num_expected connections, and how many will be writers */
static size_t max_readers, max_writers;
/* How many raeaders and writers still going */
static size_t num_readers, num_writers;
/* How many times to do the write */
static size_t write_iterations;
/* The buffer to write */
static char writebuf[256];
/* We need this for readers, though we don't actually care! */
static size_t len_ignored;
struct timemono start_time;
static void finished(void)
{
struct timerel elapsed = timemono_since(start_time);
printf("Finished: %"PRIu64"usec\n", time_to_usec(elapsed));
exit(0);
}
static struct io_plan *write_loop(struct io_conn *conn, ptrint_t *iter)
{
ptrdiff_t n = ptr2int(iter);
if (n > write_iterations) {
--num_writers;
if (num_writers == 0)
finished();
return io_wait(conn, conn, io_never, NULL);
}
return io_write(conn, writebuf, sizeof(writebuf), write_loop, int2ptr(n + 1));
}
static struct io_plan *read_loop(struct io_conn *conn, void *unused)
{
return io_read_partial(conn, writebuf, sizeof(writebuf), &len_ignored, read_loop, unused);
}
static void reader_failed(struct io_conn *conn, intptr_t *num)
{
err(1, "Reader %zu/%zu", (size_t)ptr2int(num), max_readers);
}
static void writer_failed(struct io_conn *conn, intptr_t *num)
{
err(1, "Writer %zu/%zu", (size_t)ptr2int(num), max_writers);
}
static struct io_plan *connection_in(struct io_conn *conn, void *sleep_on)
{
if (num_readers < max_readers) {
printf("r");
fflush(stdout);
num_readers++;
io_set_finish(conn, reader_failed, int2ptr(num_readers));
return read_loop(conn, NULL);
}
/* We assign writers last: not sure it matters, but it's more reflective
* of lightning where more recent connections tend to ask for gossip */
num_writers++;
printf("w");
fflush(stdout);
io_set_finish(conn, writer_failed, int2ptr(num_writers));
io_set_finish(conn, writer_failed, NULL);
if (num_writers < max_writers)
return io_wait(conn, sleep_on, write_loop, int2ptr(0));
/* Everyone is connected. Wake them and start final one */
io_wake(sleep_on);
printf("Starting!\n");
start_time = time_mono();
return write_loop(conn, int2ptr(0));
}
int main(int argc, char *argv[])
{
int fd;
struct sockaddr_in s4;
int on = 1;
if (argc != 5)
errx(1, "Usage: <portnum> <num-idle> <num-streaming> <mb-streamed>");
memset(&s4, 0, sizeof(s4));
s4.sin_family = AF_INET;
s4.sin_port = htons(atol(argv[1]));
s4.sin_addr.s_addr = INADDR_ANY;
max_readers = atol(argv[2]);
max_writers = atol(argv[3]);
write_iterations = atol(argv[4]) * (1024 * 1024 / sizeof(writebuf));
fd = socket(AF_INET, SOCK_STREAM, 0);
if (fd < 0)
err(1, "Creating socket");
/* Re-use, please.. */
if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)))
err(1, "Setting reuseaddr");
if (bind(fd, &s4, sizeof(s4)) != 0)
err(1, "Binding");
if (listen(fd, 1) != 0)
err(1, "Listening");
io_new_listener(NULL, fd, connection_in, &s4);
io_loop(NULL, NULL);
errx(1, "Sockets exited?");
}

View File

@ -4,6 +4,12 @@
#include <ccan/io/io_plan.h>
#include <errno.h>
static void destroy_conn_close_send_fd(struct io_conn *conn,
struct io_plan_arg *arg)
{
close(arg->u1.s);
}
static int do_fd_send(int fd, struct io_plan_arg *arg)
{
if (!fdpass_send(fd, arg->u1.s)) {
@ -12,8 +18,11 @@ static int do_fd_send(int fd, struct io_plan_arg *arg)
return 0;
return -1;
}
if (arg->u2.s)
if (arg->u2.vp) {
struct io_conn *conn = arg->u2.vp;
close(arg->u1.s);
tal_del_destructor2(conn, destroy_conn_close_send_fd, arg);
}
return 1;
}
@ -26,7 +35,11 @@ struct io_plan *io_send_fd_(struct io_conn *conn,
struct io_plan_arg *arg = io_plan_arg(conn, IO_OUT);
arg->u1.s = fd;
arg->u2.s = fdclose;
/* We need conn ptr for destructor */
arg->u2.vp = fdclose ? conn : NULL;
/* If conn closes before sending, we still need to close fd */
if (fdclose)
tal_add_destructor2(conn, destroy_conn_close_send_fd, arg);
return io_set_plan(conn, IO_OUT, do_fd_send, next, next_arg);
}
@ -39,7 +52,9 @@ static int do_fd_recv(int fd, struct io_plan_arg *arg)
/* In case ccan/io ever gets smart with non-blocking. */
if (errno == EAGAIN || errno == EWOULDBLOCK)
return 0;
return -1;
/* If they can't handle the error, this will close conn! */
if (!io_get_extended_errors())
return -1;
}
*(int *)arg->u1.vp = fdin;
return 1;

View File

@ -45,8 +45,9 @@ struct io_plan *io_send_fd_(struct io_conn *conn,
* @arg: @next argument
*
* This creates a plan to receive a file descriptor, as sent by
* io_send_fd. Once it's all read, the @next function will be called:
* on an error, the finish function is called instead.
* io_send_fd. Once it's all read, the @next function will be called.
* On an error, if io_get_extended_errors() is true, then @next is called
* and @fd will be -1, otherwise the finish function is called.
*
* Note that the I/O may actually be done immediately.
*

View File

@ -15,6 +15,7 @@
void *io_loop_return;
struct io_plan io_conn_freed;
static bool io_extended_errors;
struct io_listener *io_new_listener_(const tal_t *ctx, int fd,
struct io_plan *(*init)(struct io_conn *,
@ -383,9 +384,19 @@ void io_wake(const void *wait)
backend_wake(wait);
}
/* Returns false if this should not be touched (eg. freed). */
static bool do_plan(struct io_conn *conn, struct io_plan *plan,
bool idle_on_epipe)
enum plan_result {
/* Destroyed, do not touch */
FREED,
/* Worked, call again. */
KEEP_GOING,
/* Failed with EAGAIN or did partial. */
EXHAUSTED,
/* No longer interested in read (or write) */
UNINTERESTED
};
static enum plan_result do_plan(struct io_conn *conn, struct io_plan *plan,
bool idle_on_epipe)
{
/* We shouldn't have polled for this event if this wasn't true! */
assert(plan->status == IO_POLLING_NOTSTARTED
@ -393,18 +404,26 @@ static bool do_plan(struct io_conn *conn, struct io_plan *plan,
switch (plan->io(conn->fd.fd, &plan->arg)) {
case -1:
/* This is expected, as we call optimistically! */
if (errno == EAGAIN)
return EXHAUSTED;
if (errno == EPIPE && idle_on_epipe) {
plan->status = IO_UNSET;
backend_new_plan(conn);
return false;
return UNINTERESTED;
}
io_close(conn);
return false;
return FREED;
case 0:
plan->status = IO_POLLING_STARTED;
return true;
/* If it started but didn't finish, don't call again. */
return EXHAUSTED;
case 1:
return next_plan(conn, plan);
if (!next_plan(conn, plan))
return FREED;
if (plan->status == IO_POLLING_NOTSTARTED)
return KEEP_GOING;
return UNINTERESTED;
default:
/* IO should only return -1, 0 or 1 */
abort();
@ -413,16 +432,43 @@ static bool do_plan(struct io_conn *conn, struct io_plan *plan,
void io_ready(struct io_conn *conn, int pollflags)
{
if (pollflags & POLLIN)
if (!do_plan(conn, &conn->plan[IO_IN], false))
return;
enum plan_result res;
if (pollflags & POLLOUT)
/* If we're writing to a closed pipe, we need to wait for
* read to fail if we're duplex: we want to drain it! */
do_plan(conn, &conn->plan[IO_OUT],
conn->plan[IO_IN].status == IO_POLLING_NOTSTARTED
|| conn->plan[IO_IN].status == IO_POLLING_STARTED);
if (pollflags & POLLIN) {
for (;;) {
res = do_plan(conn, &conn->plan[IO_IN], false);
switch (res) {
case FREED:
return;
case EXHAUSTED:
case UNINTERESTED:
goto try_write;
case KEEP_GOING:
continue;
}
abort();
}
}
try_write:
if (pollflags & POLLOUT) {
for (;;) {
/* If we're writing to a closed pipe, we need to wait for
* read to fail if we're duplex: we want to drain it! */
res = do_plan(conn, &conn->plan[IO_OUT],
conn->plan[IO_IN].status == IO_POLLING_NOTSTARTED
|| conn->plan[IO_IN].status == IO_POLLING_STARTED);
switch (res) {
case FREED:
case EXHAUSTED:
case UNINTERESTED:
return;
case KEEP_GOING:
continue;
}
abort();
}
}
}
void io_do_always(struct io_plan *plan)
@ -540,7 +586,7 @@ struct io_plan *io_sock_shutdown(struct io_conn *conn)
/* And leave unset .*/
return &conn->plan[IO_IN];
}
bool io_flush_sync(struct io_conn *conn)
{
struct io_plan *plan = &conn->plan[IO_OUT];
@ -576,3 +622,13 @@ again:
io_fd_block(io_conn_fd(conn), false);
return ok;
}
void io_set_extended_errors(bool state)
{
io_extended_errors = state;
}
bool io_get_extended_errors(void)
{
return io_extended_errors;
}

View File

@ -59,7 +59,7 @@ struct io_conn;
io_new_conn_((ctx), (fd), \
typesafe_cb_preargs(struct io_plan *, void *, \
(init), (arg), \
struct io_conn *conn), \
struct io_conn *), \
(void *)(arg))
struct io_conn *io_new_conn_(const tal_t *ctx, int fd,
@ -113,6 +113,8 @@ void io_set_finish_(struct io_conn *conn,
* (tal'ocated off @ctx) and pass that to init(). Note that if there is
* an error on this file descriptor, it will be freed.
*
* Note: if the accept fails (usually due to EMFILE), init() will be called
* wth
* Returns NULL on error (and sets errno).
*
* Example:
@ -823,4 +825,13 @@ int (*io_poll_override(int (*poll)(struct pollfd *fds, nfds_t nfds, int timeout)
*/
const void *io_have_fd(int fd, bool *listener);
/**
* io_set_extended_errors - enable callbacks for errors.
* @state: true or false.
*
* Defaults false for compatibility. See io_new_conn for what this changes.
*/
void io_set_extended_errors(bool state);
bool io_get_extended_errors(void);
#endif /* CCAN_IO_H */

View File

@ -270,10 +270,12 @@ static void accept_conn(struct io_listener *l)
{
int fd = accept(l->fd.fd, NULL, NULL);
/* FIXME: What to do here? */
if (fd < 0)
if (fd < 0) {
/* If they've enabled it, this is how we tell them */
if (io_get_extended_errors())
l->init(NULL, l->arg);
return;
}
io_new_conn(l->ctx, fd, l->init, l->arg);
}

View File

@ -18,9 +18,17 @@ static struct io_plan *init_in_conn(struct io_conn *conn, char *buf)
return io_read(conn, buf, 2, in_conn_done, NULL);
}
/* Every second time we say we're exhausted */
static int do_nothing(int fd, struct io_plan_arg *arg)
{
return 1;
static bool read_once;
read_once = !read_once;
if (read_once)
return 1;
errno = EAGAIN;
return -1;
}
static struct io_plan *dummy_write(struct io_conn *conn,

View File

@ -29,8 +29,8 @@ static bool trace_eq(const struct trace *t1, const struct trace *t2)
}
/* struct thash */
HTABLE_DEFINE_TYPE(struct trace, (const struct trace *), hash_trace, trace_eq,
thash);
HTABLE_DEFINE_NODUPS_TYPE(struct trace, (const struct trace *), hash_trace, trace_eq,
thash);
static struct thash htable
= { HTABLE_INITIALIZER(htable.raw, thash_hash, NULL) };

View File

@ -530,7 +530,7 @@ struct opt_table *opt_find_short(char arg);
* You can set bits in type e.g. (1<<OPT_USER_START) to (1<<OPT_USER_END)
* when calling _opt_register. */
#define OPT_USER_START 8
#define OPT_USER_END 15
#define OPT_USER_END 30
/* Below here are private declarations. */
/* You can use this directly to build tables, but the macros will ensure
@ -540,7 +540,7 @@ enum opt_type {
OPT_HASARG = 2, /* -f arg|--foo=arg|--foo arg */
OPT_SUBTABLE = 4, /* Actually, longopt points to a subtable... */
OPT_EARLY = 8, /* Parse this from opt_early_parse() only. */
OPT_END = 16, /* End of the table. */
OPT_END = 31, /* End of the table. */
/* Make sure no compiler will assume we never have large
* values in the enum! */

View File

@ -14,21 +14,14 @@
char *tal_strdup_(const tal_t *ctx, const char *p, const char *label)
{
/* We have to let through NULL for take(). */
return tal_dup_arr_label(ctx, char, p, p ? strlen(p) + 1: 1, 0, label);
return tal_dup_arr_label(ctx, char, p, strlen(p) + 1, 0, label);
}
char *tal_strndup_(const tal_t *ctx, const char *p, size_t n, const char *label)
{
size_t len;
size_t len = strnlen(p, n);
char *ret;
/* We have to let through NULL for take(). */
if (likely(p))
len = strnlen(p, n);
else
len = n;
ret = tal_dup_arr_label(ctx, char, p, len, 1, label);
if (ret)
ret[len] = '\0';
@ -84,9 +77,6 @@ char *tal_vfmt_(const tal_t *ctx, const char *fmt, va_list ap, const char *label
{
char *buf;
if (!fmt && taken(fmt))
return NULL;
/* A decent guess to start. */
buf = tal_arr_label(ctx, char, strlen(fmt) * 2, label);
if (!do_vfmt(&buf, 0, fmt, ap))
@ -96,9 +86,6 @@ char *tal_vfmt_(const tal_t *ctx, const char *fmt, va_list ap, const char *label
bool tal_append_vfmt(char **baseptr, const char *fmt, va_list ap)
{
if (!fmt && taken(fmt))
return false;
return do_vfmt(baseptr, strlen(*baseptr), fmt, ap);
}
@ -120,13 +107,7 @@ char *tal_strcat_(const tal_t *ctx, const char *s1, const char *s2,
size_t len1, len2;
char *ret;
if (unlikely(!s2) && taken(s2)) {
if (taken(s1))
tal_free(s1);
return NULL;
}
/* We have to let through NULL for take(). */
len1 = s1 ? strlen(s1) : 0;
len1 = strlen(s1);
len2 = strlen(s2);
ret = tal_dup_arr_label(ctx, char, s1, len1, len2 + 1, label);
@ -151,13 +132,11 @@ char **tal_strsplit_(const tal_t *ctx,
tal_free(string);
if (taken(delims))
tal_free(delims);
return NULL;
return parts;
}
str = tal_strdup(parts, string);
if (unlikely(!str))
goto fail;
if (unlikely(!delims) && is_taken(delims))
goto fail;
if (flags == STR_NO_EMPTY)
str += strspn(str, delims);
@ -185,10 +164,14 @@ char **tal_strsplit_(const tal_t *ctx,
return parts;
fail:
#ifdef CCAN_TAL_NEVER_RETURN_NULL
abort();
#else
tal_free(parts);
if (taken(delims))
tal_free(delims);
return NULL;
#endif
}
char *tal_strjoin_(const tal_t *ctx,
@ -199,12 +182,6 @@ char *tal_strjoin_(const tal_t *ctx,
char *ret = NULL;
size_t totlen = 0, dlen;
if (unlikely(!strings) && is_taken(strings))
goto fail;
if (unlikely(!delim) && is_taken(delim))
goto fail;
dlen = strlen(delim);
ret = tal_arr_label(ctx, char, dlen*2+1, label);
if (!ret)
@ -269,15 +246,9 @@ bool tal_strreg_(const tal_t *ctx, const char *string, const char *label,
unsigned int i;
va_list ap;
if (unlikely(!regex) && is_taken(regex))
goto fail_no_re;
if (regcomp(&r, regex, REG_EXTENDED) != 0)
goto fail_no_re;
if (unlikely(!string) && is_taken(string))
goto fail;
if (regexec(&r, string, nmatch, matches, 0) != 0)
goto fail;

View File

@ -12,17 +12,18 @@
/**
* tal_strdup - duplicate a string
* @ctx: NULL, or tal allocated object to be parent.
* @p: the string to copy (can be take()).
* @p: the string to copy (can be take(), must not be NULL).
*
* The returned string will have tal_count() == strlen() + 1.
*/
#define tal_strdup(ctx, p) tal_strdup_(ctx, p, TAL_LABEL(char, "[]"))
char *tal_strdup_(const tal_t *ctx, const char *p TAKES, const char *label);
char *tal_strdup_(const tal_t *ctx, const char *p TAKES, const char *label)
TAL_RETURN_PTR NON_NULL_ARGS(2);
/**
* tal_strndup - duplicate a limited amount of a string.
* @ctx: NULL, or tal allocated object to be parent.
* @p: the string to copy (can be take()).
* @p: the string to copy (can be take(), must not be NULL).
* @n: the maximum length to copy.
*
* Always gives a nul-terminated string, with strlen() <= @n.
@ -30,24 +31,25 @@ char *tal_strdup_(const tal_t *ctx, const char *p TAKES, const char *label);
*/
#define tal_strndup(ctx, p, n) tal_strndup_(ctx, p, n, TAL_LABEL(char, "[]"))
char *tal_strndup_(const tal_t *ctx, const char *p TAKES, size_t n,
const char *label);
const char *label)
TAL_RETURN_PTR NON_NULL_ARGS(2);
/**
* tal_fmt - allocate a formatted string
* @ctx: NULL, or tal allocated object to be parent.
* @fmt: the printf-style format (can be take()).
* @fmt: the printf-style format (can be take(), must not be NULL).
*
* The returned string will have tal_count() == strlen() + 1.
*/
#define tal_fmt(ctx, ...) \
tal_fmt_(ctx, TAL_LABEL(char, "[]"), __VA_ARGS__)
char *tal_fmt_(const tal_t *ctx, const char *label, const char *fmt TAKES,
...) PRINTF_FMT(3,4);
...) PRINTF_FMT(3,4) TAL_RETURN_PTR NON_NULL_ARGS(3);
/**
* tal_vfmt - allocate a formatted string (va_list version)
* @ctx: NULL, or tal allocated object to be parent.
* @fmt: the printf-style format (can be take()).
* @fmt: the printf-style format (can be take(), must not be NULL).
* @va: the va_list containing the format args.
*
* The returned string will have tal_count() == strlen() + 1.
@ -56,40 +58,42 @@ char *tal_fmt_(const tal_t *ctx, const char *label, const char *fmt TAKES,
tal_vfmt_(ctx, fmt, va, TAL_LABEL(char, "[]"))
char *tal_vfmt_(const tal_t *ctx, const char *fmt TAKES, va_list ap,
const char *label)
PRINTF_FMT(2,0);
PRINTF_FMT(2,0) TAL_RETURN_PTR NON_NULL_ARGS(2);
/**
* tal_append_fmt - append a formatted string to a talloc string.
* @baseptr: a pointer to the tal string to be appended to.
* @fmt: the printf-style format (can be take()).
* @fmt: the printf-style format (can be take(), must not be NULL).
*
* Returns false on allocation failure.
* Otherwise tal_count(*@baseptr) == strlen(*@baseptr) + 1.
*/
bool tal_append_fmt(char **baseptr, const char *fmt TAKES, ...) PRINTF_FMT(2,3);
bool tal_append_fmt(char **baseptr, const char *fmt TAKES, ...)
PRINTF_FMT(2,3) NON_NULL_ARGS(2);
/**
* tal_append_vfmt - append a formatted string to a talloc string (va_list)
* @baseptr: a pointer to the tal string to be appended to.
* @fmt: the printf-style format (can be take()).
* @fmt: the printf-style format (can be take(), must not be NULL).
* @va: the va_list containing the format args.
*
* Returns false on allocation failure.
* Otherwise tal_count(*@baseptr) == strlen(*@baseptr) + 1.
*/
bool tal_append_vfmt(char **baseptr, const char *fmt TAKES, va_list ap);
bool tal_append_vfmt(char **baseptr, const char *fmt TAKES, va_list ap)
NON_NULL_ARGS(2);
/**
* tal_strcat - join two strings together
* @ctx: NULL, or tal allocated object to be parent.
* @s1: the first string (can be take()).
* @s2: the second string (can be take()).
* @s1: the first string (can be take(), must not be NULL).
* @s2: the second string (can be take(), must not be NULL).
*
* The returned string will have tal_count() == strlen() + 1.
*/
#define tal_strcat(ctx, s1, s2) tal_strcat_(ctx, s1, s2, TAL_LABEL(char, "[]"))
char *tal_strcat_(const tal_t *ctx, const char *s1 TAKES, const char *s2 TAKES,
const char *label);
const char *label) TAL_RETURN_PTR NON_NULL_ARGS(2,3);
enum strsplit {
STR_EMPTY_OK,
@ -99,8 +103,8 @@ enum strsplit {
/**
* tal_strsplit - Split string into an array of substrings
* @ctx: the context to tal from (often NULL).
* @string: the string to split (can be take()).
* @delims: delimiters where lines should be split (can be take()).
* @string: the string to split (can be take(), must not be NULL).
* @delims: delimiters where lines should be split (can be take(), must not be NULL).
* @flags: whether to include empty substrings.
*
* This function splits a single string into multiple strings.
@ -137,7 +141,8 @@ char **tal_strsplit_(const tal_t *ctx,
const char *string TAKES,
const char *delims TAKES,
enum strsplit flag,
const char *label);
const char *label)
TAL_RETURN_PTR NON_NULL_ARGS(2,3);
enum strjoin {
STR_TRAIL,
@ -147,8 +152,8 @@ enum strjoin {
/**
* tal_strjoin - Join an array of substrings into one long string
* @ctx: the context to tal from (often NULL).
* @strings: the NULL-terminated array of strings to join (can be take())
* @delim: the delimiter to insert between the strings (can be take())
* @strings: the NULL-terminated array of strings to join (can be take(), must not be NULL)
* @delim: the delimiter to insert between the strings (can be take(), must not be NULL)
* @flags: whether to add a delimieter to the end
*
* This function joins an array of strings into a single string. The
@ -175,13 +180,14 @@ char *tal_strjoin_(const void *ctx,
char *strings[] TAKES,
const char *delim TAKES,
enum strjoin flags,
const char *label);
const char *label)
TAL_RETURN_PTR NON_NULL_ARGS(2,3);
/**
* tal_strreg - match/extract from a string via (extended) regular expressions.
* @ctx: the context to tal from (often NULL)
* @string: the string to try to match (can be take())
* @regex: the regular expression to match (can be take())
* @string: the string to try to match (can be take(), must not be NULL)
* @regex: the regular expression to match (can be take(), must not be NULL)
* ...: pointers to strings to allocate for subexpressions.
*
* Returns true if we matched, in which case any parenthesized
@ -221,5 +227,6 @@ char *tal_strjoin_(const void *ctx,
#define tal_strreg(ctx, string, ...) \
tal_strreg_(ctx, string, TAL_LABEL(char, "[]"), __VA_ARGS__)
bool tal_strreg_(const void *ctx, const char *string TAKES,
const char *label, const char *regex, ...);
const char *label, const char *regex TAKES, ...)
NON_NULL_ARGS(2,4);
#endif /* CCAN_STR_TAL_H */

View File

@ -456,13 +456,24 @@ static void del_tree(struct tal_hdr *t, const tal_t *orig, int saved_errno)
freefn(t);
}
/* Don't have compiler complain we're returning NULL if we promised not to! */
static void *null_alloc_failed(void)
{
#ifdef CCAN_TAL_NEVER_RETURN_NULL
abort();
#else
return NULL;
#endif /* CCAN_TAL_NEVER_RETURN_NULL */
}
void *tal_alloc_(const tal_t *ctx, size_t size, bool clear, const char *label)
{
struct tal_hdr *child, *parent = debug_tal(to_tal_hdr_or_null(ctx));
child = allocate(sizeof(struct tal_hdr) + size);
if (!child)
return NULL;
return null_alloc_failed();
if (clear)
memset(from_tal_hdr(child), 0, size);
child->prop = (void *)label;
@ -470,7 +481,7 @@ void *tal_alloc_(const tal_t *ctx, size_t size, bool clear, const char *label)
if (!add_child(parent, child)) {
freefn(child);
return NULL;
return null_alloc_failed();
}
debug_tal(parent);
if (notifiers)
@ -501,7 +512,7 @@ void *tal_alloc_arr_(const tal_t *ctx, size_t size, size_t count, bool clear,
const char *label)
{
if (!adjust_size(&size, count))
return NULL;
return null_alloc_failed();
return tal_alloc_(ctx, size, clear, label);
}

View File

@ -11,6 +11,14 @@
#include <stdbool.h>
#include <stdarg.h>
/* Define this for better optimization if you never override errfn
* to something tat returns */
#ifdef CCAN_TAL_NEVER_RETURN_NULL
#define TAL_RETURN_PTR RETURNS_NONNULL
#else
#define TAL_RETURN_PTR
#endif /* CCAN_TAL_NEVER_RETURN_NULL */
/**
* tal_t - convenient alias for void to mark tal pointers.
*
@ -417,7 +425,8 @@ tal_t *tal_parent(const tal_t *ctx);
* @error_fn: called on errors or NULL (default is abort)
*
* The defaults are set up so tal functions never return NULL, but you
* can override erorr_fn to change that. error_fn can return, and is
* can override error_fn to change that. error_fn can return (only if
* you haven't defined CCAN_TAL_NEVER_RETURN_NULL!), and is
* called if alloc_fn or resize_fn fail.
*
* If any parameter is NULL, that function is unchanged.
@ -521,9 +530,11 @@ bool tal_set_name_(tal_t *ctx, const char *name, bool literal);
#define tal_typechk_(ptr, ptype) (ptr)
#endif
void *tal_alloc_(const tal_t *ctx, size_t bytes, bool clear, const char *label);
void *tal_alloc_(const tal_t *ctx, size_t bytes, bool clear, const char *label)
TAL_RETURN_PTR;
void *tal_alloc_arr_(const tal_t *ctx, size_t bytes, size_t count, bool clear,
const char *label);
const char *label)
TAL_RETURN_PTR;
void *tal_dup_(const tal_t *ctx, const void *p TAKES, size_t size,
size_t n, size_t extra, bool nullok, const char *label);

View File

@ -147,7 +147,7 @@
* It evaluates to @x so you can chain it.
*/
#define tcon_check_ptr(x, canary, expr) \
(sizeof((expr) ? (expr) : &(x)->_tcon[0].canary) ? (x) : (x))
(sizeof(0 ? (expr) : &(x)->_tcon[0].canary) ? (x) : (x))
/**
* tcon_type - the type within a container (or void *)

View File

@ -7,13 +7,13 @@ int main(void)
struct timemono t1, t2;
struct timerel t3;
plan_tests(5);
plan_tests(10);
/* Test time_mono */
t1 = time_mono();
t2 = time_mono();
ok1(!time_less_(t2.ts, t1.ts));
ok1(!timemono_before(t2, t1));
t3.ts.tv_sec = 1;
t3.ts.tv_nsec = 0;
@ -24,5 +24,11 @@ int main(void)
ok1(timemono_add(t1, t3).ts.tv_sec == t1.ts.tv_sec + 1);
ok1(timemono_add(t2, t3).ts.tv_nsec == t2.ts.tv_nsec);
ok1(timemono_sub(timemono_add(t1, t3), t3).ts.tv_sec == t1.ts.tv_sec);
ok1(timemono_sub(timemono_add(t1, t3), t3).ts.tv_nsec == t1.ts.tv_nsec);
ok1(timemono_after(timemono_add(t1, t3), t1));
ok1(!timemono_after(t1, timemono_add(t1, t3)));
ok1(!timemono_after(t1, t1));
return exit_status();
}

View File

@ -193,6 +193,23 @@ static inline bool time_greater(struct timerel a, struct timerel b)
return time_greater_(a.ts, b.ts);
}
/**
* timemono_after - is a after b?
* @a: one monotonic time.
* @b: another monotonic time.
*
* Example:
* static bool timed_out(const struct timemono *start)
* {
* #define TIMEOUT time_from_msec(1000)
* return timemono_after(time_mono(), timemono_add(*start, TIMEOUT));
* }
*/
static inline bool timemono_after(struct timemono a, struct timemono b)
{
return time_greater_(a.ts, b.ts);
}
static inline bool time_less_(struct timespec a, struct timespec b)
{
if (TIME_CHECK(a).tv_sec < TIME_CHECK(b).tv_sec)
@ -220,6 +237,23 @@ static inline bool time_before(struct timeabs a, struct timeabs b)
return time_less_(a.ts, b.ts);
}
/**
* timemono_before - is a before b?
* @a: one monotonic time.
* @b: another monotonic time.
*
* Example:
* static bool still_valid(const struct timemono *start)
* {
* #define TIMEOUT time_from_msec(1000)
* return timemono_before(time_mono(), timemono_add(*start, TIMEOUT));
* }
*/
static inline bool timemono_before(struct timemono a, struct timemono b)
{
return time_less_(a.ts, b.ts);
}
/**
* time_less - is a before b?
* @a: one relative time.
@ -404,6 +438,29 @@ static inline struct timeabs timeabs_sub(struct timeabs abs, struct timerel rel)
return t;
}
/**
* timemono_sub - subtract a relative time from a monotonic time
* @mono: the monotonic time.
* @rel: the relative time.
*
* This returns a well formed struct timemono of @mono - @rel.
*
* Example:
* // We do one every second.
* static struct timemono previous_time(void)
* {
* return timemono_sub(time_mono(), time_from_msec(1000));
* }
*/
static inline struct timemono timemono_sub(struct timemono mono, struct timerel rel)
{
struct timemono t;
t.ts = time_sub_(mono.ts, rel.ts);
return t;
}
static inline struct timespec time_add_(struct timespec a, struct timespec b)
{
struct timespec sum;
@ -488,6 +545,8 @@ static inline struct timerel timerel_add(struct timerel a, struct timerel b)
* @div: number to divide it by.
*
* Example:
* #include <sys/wait.h>
*
* // How long does it take to do a fork?
* static struct timerel forking_time(void)
* {

View File

@ -95,8 +95,6 @@ CHANNELD_COMMON_OBJS := \
common/version.o \
common/wire_error.o \
common/wireaddr.o \
gossipd/gossipd_peerd_wiregen.o \
gossipd/gossip_store_wiregen.o \
wire/fromwire.o \
wire/towire.o

File diff suppressed because it is too large Load Diff

View File

@ -27,7 +27,7 @@ struct htlc {
const u8 *routing;
/* Blinding (optional). */
struct pubkey *blinding;
struct pubkey *path_key;
/* Should we immediately fail this htlc? */
bool fail_immediate;
@ -56,7 +56,8 @@ static inline size_t htlc_hash(u64 id)
{
return siphash24(siphash_seed(), &id, sizeof(id));
}
HTABLE_DEFINE_TYPE(struct htlc, htlc_key, htlc_hash, htlc_cmp, htlc_map);
HTABLE_DEFINE_DUPS_TYPE(struct htlc, htlc_key, htlc_hash, htlc_cmp,
htlc_map);
static inline struct htlc *htlc_get(struct htlc_map *htlcs, u64 id, enum side owner)
{

View File

@ -72,7 +72,6 @@ msgdata,channeld_init,desired_type,channel_type,
msgdata,channeld_init,dev_disable_commit,?u32,
msgdata,channeld_init,num_penalty_bases,u32,
msgdata,channeld_init,pbases,penalty_base,num_penalty_bases
msgdata,channeld_init,reestablish_only,bool,
msgdata,channeld_init,experimental_upgrade,bool,
msgdata,channeld_init,num_inflights,u16,
msgdata,channeld_init,inflights,inflight,num_inflights
@ -95,7 +94,7 @@ msgdata,channeld_offer_htlc,amount_msat,amount_msat,
msgdata,channeld_offer_htlc,cltv_expiry,u32,
msgdata,channeld_offer_htlc,payment_hash,sha256,
msgdata,channeld_offer_htlc,onion_routing_packet,u8,1366
msgdata,channeld_offer_htlc,blinding,?pubkey,
msgdata,channeld_offer_htlc,path_key,?pubkey,
# Reply; synchronous since IDs have to increment.
msgtype,channeld_offer_htlc_reply,1104
@ -210,6 +209,7 @@ msgdata,channeld_splice_init,psbt,wally_psbt,
msgdata,channeld_splice_init,relative_amount,s64,
msgdata,channeld_splice_init,feerate_per_kw,u32,
msgdata,channeld_splice_init,force_feerate,bool,
msgdata,channeld_splice_init,skip_stfu,bool,
# channeld->master: hello, I started a channel splice open
msgtype,channeld_splice_confirmed_init,7205
@ -223,6 +223,7 @@ msgdata,channeld_splice_update,psbt,wally_psbt,
msgtype,channeld_splice_confirmed_update,7207
msgdata,channeld_splice_confirmed_update,psbt,wally_psbt,
msgdata,channeld_splice_confirmed_update,commitments_secured,bool,
msgdata,channeld_splice_confirmed_update,signatures_secured,bool,
# channeld->master: Lookup a transaction
msgtype,channeld_splice_lookup_tx,7208
@ -253,6 +254,7 @@ msgdata,channeld_splice_feerate_error,too_high,bool,
# channeld->master: Add an inflight to the DB
msgtype,channeld_add_inflight,7216
msgdata,channeld_add_inflight,remote_funding,pubkey,
msgdata,channeld_add_inflight,tx_id,bitcoin_txid,
msgdata,channeld_add_inflight,tx_outnum,u32,
msgdata,channeld_add_inflight,feerate,u32,
@ -270,6 +272,7 @@ msgtype,channeld_update_inflight,7219
msgdata,channeld_update_inflight,psbt,wally_psbt,
msgdata,channeld_update_inflight,last_tx,?bitcoin_tx,
msgdata,channeld_update_inflight,last_sig,?bitcoin_signature,
msgdata,channeld_update_inflight,locked_scid,?short_channel_id,
# channeld->master: A funding error has occured
msgtype,channeld_splice_funding_error,7220
@ -285,7 +288,17 @@ msgdata,channeld_splice_state_error,state_error,wirestring,
msgtype,channeld_splice_abort,7223
msgdata,channeld_splice_abort,did_i_initiate,bool,
msgdata,channeld_splice_abort,inflight_outpoint,?bitcoin_outpoint,
msgdata,channeld_splice_abort,reason,?wirestring,
msgdata,channeld_splice_abort,reason,wirestring,
# master->channeld: Please enter stfu mode
msgtype,channeld_stfu,7224
# channeld->master: Entered stfu result
msgtype,channeld_confirmed_stfu,7225
msgdata,channeld_confirmed_stfu,available_funds,amount_msat,
# master->channeld: Please enter perform tx_abort
msgtype,channeld_abort,7226
# Tell peer to shut down channel.
msgtype,channeld_send_shutdown,1023
@ -322,8 +335,6 @@ msgdata,channeld_dev_memleak_reply,leak,bool,
# Peer presented proof it was from the future.
msgtype,channeld_fail_fallen_behind,1028
# This is NULL if option_static_remotekey.
msgdata,channeld_fail_fallen_behind,remote_per_commitment_point,?pubkey,
# When we receive announcement_signatures for channel announce
msgtype,channeld_got_announcement,1017
@ -349,3 +360,7 @@ msgdata,channeld_upgraded,new_type,channel_type,
# Tell peer about our latest and greatest blockheight.
msgtype,channeld_blockheight,1012
msgdata,channeld_blockheight,blockheight,u32,
# Tell channeld about peer's shachain seed.
msgtype,channeld_dev_peer_shachain,1013
msgdata,channeld_dev_peer_shachain,seed,sha256,

Can't render this file because it has a wrong number of fields in line 16.

View File

@ -53,7 +53,7 @@ bool commit_tx_amount_trimmed(const struct htlc **htlcs,
if (trim(htlcs[i], feerate_per_kw, dust_limit,
option_anchor_outputs, option_anchors_zero_fee_htlc_tx,
side)) {
if (!amount_msat_add(amt, *amt, htlcs[i]->amount))
if (!amount_msat_accumulate(amt, htlcs[i]->amount))
return false;
}
}

View File

@ -226,7 +226,7 @@ static bool sum_offered_msatoshis(struct amount_msat *total,
*total = AMOUNT_MSAT(0);
for (i = 0; i < tal_count(htlcs); i++) {
if (htlc_owner(htlcs[i]) == side) {
if (!amount_msat_add(total, *total, htlcs[i]->amount))
if (!amount_msat_accumulate(total, htlcs[i]->amount))
return false;
}
}
@ -241,7 +241,7 @@ static void add_htlcs(struct bitcoin_tx ***txs,
{
struct bitcoin_outpoint outpoint;
u32 htlc_feerate_per_kw;
bool option_anchor_outputs = channel_has(channel, OPT_ANCHOR_OUTPUTS);
bool option_anchor_outputs = channel_has(channel, OPT_ANCHOR_OUTPUTS_DEPRECATED);
bool option_anchors_zero_fee_htlc_tx = channel_has(channel, OPT_ANCHORS_ZERO_FEE_HTLC_TX);
if (channel_has(channel, OPT_ANCHORS_ZERO_FEE_HTLC_TX))
@ -309,13 +309,17 @@ struct bitcoin_tx **channel_txs(const tal_t *ctx,
enum side side,
s64 splice_amnt,
s64 remote_splice_amnt,
int *other_anchor_outnum)
int *other_anchor_outnum,
const struct pubkey funding_pubkeys[NUM_SIDES])
{
struct bitcoin_tx **txs;
const struct htlc **committed;
struct keyset keyset;
struct amount_msat side_pay, other_side_pay;
if (!funding_pubkeys)
funding_pubkeys = channel->funding_pubkey;
if (!derive_keyset(per_commitment_point,
&channel->basepoints[side],
&channel->basepoints[!side],
@ -329,8 +333,8 @@ struct bitcoin_tx **channel_txs(const tal_t *ctx,
/* Generating and saving witness script required to spend
* the funding output */
*funding_wscript = bitcoin_redeem_2of2(ctx,
&channel->funding_pubkey[side],
&channel->funding_pubkey[!side]);
&funding_pubkeys[side],
&funding_pubkeys[!side]);
side_pay = channel->view[side].owed[side];
other_side_pay = channel->view[side].owed[!side];
@ -351,8 +355,8 @@ struct bitcoin_tx **channel_txs(const tal_t *ctx,
txs[0] = commit_tx(
txs, funding,
funding_sats,
&channel->funding_pubkey[side],
&channel->funding_pubkey[!side],
&funding_pubkeys[side],
&funding_pubkeys[!side],
channel->opener,
channel->config[!side].to_self_delay,
channel->lease_expiry,
@ -361,15 +365,15 @@ struct bitcoin_tx **channel_txs(const tal_t *ctx,
channel->config[side].dust_limit, side_pay,
other_side_pay, committed, htlcmap, direct_outputs,
commitment_number ^ channel->commitment_number_obscurer,
channel_has(channel, OPT_ANCHOR_OUTPUTS),
channel_has(channel, OPT_ANCHOR_OUTPUTS_DEPRECATED),
channel_has(channel, OPT_ANCHORS_ZERO_FEE_HTLC_TX),
side, other_anchor_outnum);
/* Set the remote/local pubkeys on the commitment tx psbt */
psbt_input_add_pubkey(txs[0]->psbt, 0,
&channel->funding_pubkey[side], false /* is_taproot */);
&funding_pubkeys[side], false /* is_taproot */);
psbt_input_add_pubkey(txs[0]->psbt, 0,
&channel->funding_pubkey[!side], false /* is_taproot */);
&funding_pubkeys[!side], false /* is_taproot */);
add_htlcs(&txs, *htlcmap, channel, &keyset, side);
@ -462,7 +466,7 @@ static struct amount_sat fee_for_htlcs(const struct channel *channel,
u32 feerate = channel_feerate(channel, side);
struct amount_sat dust_limit = channel->config[side].dust_limit;
size_t untrimmed;
bool option_anchor_outputs = channel_has(channel, OPT_ANCHOR_OUTPUTS);
bool option_anchor_outputs = channel_has(channel, OPT_ANCHOR_OUTPUTS_DEPRECATED);
bool option_anchors_zero_fee_htlc_tx = channel_has(channel, OPT_ANCHORS_ZERO_FEE_HTLC_TX);
untrimmed = num_untrimmed_htlcs(side, dust_limit, feerate,
@ -484,7 +488,7 @@ static bool htlc_dust(const struct channel *channel,
struct amount_msat *trim_total)
{
struct amount_sat dust_limit = channel->config[side].dust_limit;
bool option_anchor_outputs = channel_has(channel, OPT_ANCHOR_OUTPUTS);
bool option_anchor_outputs = channel_has(channel, OPT_ANCHOR_OUTPUTS_DEPRECATED);
bool option_anchors_zero_fee_htlc_tx = channel_has(channel, OPT_ANCHORS_ZERO_FEE_HTLC_TX);
struct amount_msat trim_rmvd = AMOUNT_MSAT(0);
@ -522,7 +526,7 @@ static bool htlc_dust(const struct channel *channel,
*
* To mostly avoid this situation, at least from our side, we apply an
* additional constraint when we're opener trying to add an HTLC: make
* sure we can afford one more HTLC, even if fees increase by 100%.
* sure we can afford one more HTLC, even if fees increase.
*
* We could do this for the peer, as well, by rejecting their HTLC
* immediately in this case. But rejecting a remote HTLC here causes
@ -544,7 +548,7 @@ static bool local_opener_has_fee_headroom(const struct channel *channel,
u32 feerate = channel_feerate(channel, LOCAL);
size_t untrimmed;
struct amount_sat fee;
bool option_anchor_outputs = channel_has(channel, OPT_ANCHOR_OUTPUTS);
bool option_anchor_outputs = channel_has(channel, OPT_ANCHOR_OUTPUTS_DEPRECATED);
bool option_anchors_zero_fee_htlc_tx = channel_has(channel, OPT_ANCHORS_ZERO_FEE_HTLC_TX);
assert(channel->opener == LOCAL);
@ -559,17 +563,17 @@ static bool local_opener_has_fee_headroom(const struct channel *channel,
/* Now, how much would it cost us if feerate increases 100% and we added
* another HTLC? */
fee = commit_tx_base_fee(2 * feerate, untrimmed + 1,
fee = commit_tx_base_fee(marginal_feerate(feerate), untrimmed + 1,
option_anchor_outputs,
option_anchors_zero_fee_htlc_tx);
if (amount_msat_greater_eq_sat(remainder, fee))
return true;
status_debug("Adding HTLC would leave us only %s: we need %s for"
" another HTLC if fees increase by 100%% to %uperkw",
" another HTLC if fees increase from %uperkw to %uperkw",
fmt_amount_msat(tmpctx, remainder),
fmt_amount_sat(tmpctx, fee),
feerate + feerate);
feerate, marginal_feerate(feerate));
return false;
}
@ -580,7 +584,7 @@ static enum channel_add_err add_htlc(struct channel *channel,
u32 cltv_expiry,
const struct sha256 *payment_hash,
const u8 routing[TOTAL_PACKET_SIZE(ROUTING_INFO_SIZE)],
const struct pubkey *blinding TAKES,
const struct pubkey *path_key TAKES,
struct htlc **htlcp,
bool enforce_aggregate_limits,
struct amount_sat *htlc_fee,
@ -593,7 +597,7 @@ static enum channel_add_err add_htlc(struct channel *channel,
const struct htlc **committed, **adding, **removing;
const struct channel_view *view;
size_t htlc_count;
bool option_anchor_outputs = channel_has(channel, OPT_ANCHOR_OUTPUTS);
bool option_anchor_outputs = channel_has(channel, OPT_ANCHOR_OUTPUTS_DEPRECATED);
bool option_anchors_zero_fee_htlc_tx = channel_has(channel, OPT_ANCHORS_ZERO_FEE_HTLC_TX);
u32 feerate, feerate_ceil;
@ -605,7 +609,7 @@ static enum channel_add_err add_htlc(struct channel *channel,
htlc->fail_immediate = false;
htlc->rhash = *payment_hash;
htlc->blinding = tal_dup_or_null(htlc, struct pubkey, blinding);
htlc->path_key = tal_dup_or_null(htlc, struct pubkey, path_key);
htlc->failed = NULL;
htlc->r = NULL;
htlc->routing = tal_dup_arr(htlc, u8, routing, TOTAL_PACKET_SIZE(ROUTING_INFO_SIZE), 0);
@ -647,7 +651,7 @@ static enum channel_add_err add_htlc(struct channel *channel,
* - SHOULD send a `warning` and close the connection, or send an
* `error` and fail the channel.
*/
if (amount_msat_eq(htlc->amount, AMOUNT_MSAT(0))) {
if (amount_msat_is_zero(htlc->amount)) {
return CHANNEL_ERR_HTLC_BELOW_MINIMUM;
}
if (amount_msat_less(htlc->amount, channel->config[recipient].htlc_minimum)) {
@ -898,7 +902,7 @@ enum channel_add_err channel_add_htlc(struct channel *channel,
u32 cltv_expiry,
const struct sha256 *payment_hash,
const u8 routing[TOTAL_PACKET_SIZE(ROUTING_INFO_SIZE)],
const struct pubkey *blinding TAKES,
const struct pubkey *path_key TAKES,
struct htlc **htlcp,
struct amount_sat *htlc_fee,
bool err_immediate_failures)
@ -918,7 +922,7 @@ enum channel_add_err channel_add_htlc(struct channel *channel,
status_broken("Peer sent out-of-order HTLC ids (is that you, old c-lightning node?)");
return add_htlc(channel, state, id, amount, cltv_expiry,
payment_hash, routing, blinding,
payment_hash, routing, path_key,
htlcp, true, htlc_fee, err_immediate_failures);
}
@ -1217,7 +1221,7 @@ u32 approx_max_feerate(const struct channel *channel)
struct amount_msat avail;
struct balance balance;
const struct htlc **committed, **adding, **removing;
bool option_anchor_outputs = channel_has(channel, OPT_ANCHOR_OUTPUTS);
bool option_anchor_outputs = channel_has(channel, OPT_ANCHOR_OUTPUTS_DEPRECATED);
bool option_anchors_zero_fee_htlc_tx = channel_has(channel, OPT_ANCHORS_ZERO_FEE_HTLC_TX);
gather_htlcs(tmpctx, channel, !channel->opener,
@ -1298,7 +1302,7 @@ bool can_opener_afford_feerate(const struct channel *channel, u32 feerate_per_kw
struct amount_sat dust_limit = channel->config[!channel->opener].dust_limit;
size_t untrimmed;
const struct htlc **committed, **adding, **removing;
bool option_anchor_outputs = channel_has(channel, OPT_ANCHOR_OUTPUTS);
bool option_anchor_outputs = channel_has(channel, OPT_ANCHOR_OUTPUTS_DEPRECATED);
bool option_anchors_zero_fee_htlc_tx = channel_has(channel, OPT_ANCHORS_ZERO_FEE_HTLC_TX);
struct balance balance;
struct amount_msat available;
@ -1616,7 +1620,7 @@ bool channel_force_htlcs(struct channel *channel,
htlcs[i]->cltv_expiry,
&htlcs[i]->payment_hash,
htlcs[i]->onion_routing_packet,
htlcs[i]->blinding,
htlcs[i]->path_key,
&htlc, false, NULL, false);
if (e != CHANNEL_ERR_ADD_OK) {
status_broken("%s HTLC %"PRIu64" failed error %u",
@ -1654,13 +1658,13 @@ bool channel_force_htlcs(struct channel *channel,
const char *channel_add_err_name(enum channel_add_err e)
{
static char invalidbuf[sizeof("INVALID ") + STR_MAX_CHARS(e)];
static char invalidbuf[sizeof("UNKNOWN ") + STR_MAX_CHARS(e)];
for (size_t i = 0; enum_channel_add_err_names[i].name; i++) {
if (enum_channel_add_err_names[i].v == e)
return enum_channel_add_err_names[i].name;
}
snprintf(invalidbuf, sizeof(invalidbuf), "INVALID %i", e);
snprintf(invalidbuf, sizeof(invalidbuf), "UNKNOWN %i", e);
return invalidbuf;
}

View File

@ -67,6 +67,7 @@ struct channel *new_full_channel(const tal_t *ctx,
* @local_splice_amnt: how much is being spliced in (or out, if -ve) of local side.
* @remote_splice_amnt: how much is being spliced in (or out, if -ve) of remote side.
* @other_anchor_outnum: which output (-1 if none) is the !!side anchor
* @funding_pubkeys: The funding pubkeys (specify NULL to use channel's value).
*
* Returns the unsigned commitment transaction for the committed state
* for @side, followed by the htlc transactions in output order and
@ -84,7 +85,8 @@ struct bitcoin_tx **channel_txs(const tal_t *ctx,
enum side side,
s64 local_splice_amnt,
s64 remote_splice_amnt,
int *local_anchor_outnum);
int *local_anchor_outnum,
const struct pubkey funding_pubkeys[NUM_SIDES]);
/**
* actual_feerate: what is the actual feerate for the local side.

View File

@ -1,6 +1,7 @@
#include "config.h"
#include <assert.h>
#include <bitcoin/psbt.h>
#include <bitcoin/short_channel_id.h>
#include <channeld/inflight.h>
#include <wire/wire.h>
@ -9,6 +10,7 @@ struct inflight *fromwire_inflight(const tal_t *ctx, const u8 **cursor, size_t *
struct inflight *inflight = tal(ctx, struct inflight);
fromwire_bitcoin_outpoint(cursor, max, &inflight->outpoint);
fromwire_pubkey(cursor, max, &inflight->remote_funding);
inflight->amnt = fromwire_amount_sat(cursor, max);
inflight->remote_tx_sigs = fromwire_bool(cursor, max);
inflight->psbt = fromwire_wally_psbt(inflight, cursor, max);
@ -24,6 +26,14 @@ struct inflight *fromwire_inflight(const tal_t *ctx, const u8 **cursor, size_t *
}
inflight->i_am_initiator = fromwire_bool(cursor, max);
inflight->force_sign_first = fromwire_bool(cursor, max);
int has_locked_scid = fromwire_u8(cursor, max);
if (has_locked_scid) {
inflight->locked_scid = tal(inflight, struct short_channel_id);
*inflight->locked_scid = fromwire_short_channel_id(cursor, max);
}
else {
inflight->locked_scid = NULL;
}
return inflight;
}
@ -31,6 +41,7 @@ struct inflight *fromwire_inflight(const tal_t *ctx, const u8 **cursor, size_t *
void towire_inflight(u8 **pptr, const struct inflight *inflight)
{
towire_bitcoin_outpoint(pptr, &inflight->outpoint);
towire_pubkey(pptr, &inflight->remote_funding);
towire_amount_sat(pptr, inflight->amnt);
towire_bool(pptr, inflight->remote_tx_sigs);
towire_wally_psbt(pptr, inflight->psbt);
@ -42,17 +53,7 @@ void towire_inflight(u8 **pptr, const struct inflight *inflight)
}
towire_bool(pptr, inflight->i_am_initiator);
towire_bool(pptr, inflight->force_sign_first);
}
void copy_inflight(struct inflight *dest, struct inflight *src)
{
dest->outpoint = src->outpoint;
dest->amnt = src->amnt;
dest->remote_tx_sigs = src->remote_tx_sigs;
dest->psbt = src->psbt ? clone_psbt(dest, src->psbt): NULL;
dest->splice_amnt = src->splice_amnt;
dest->last_tx = src->last_tx ? clone_bitcoin_tx(dest, src->last_tx) : NULL;
dest->last_sig = src->last_sig;
dest->i_am_initiator = src->i_am_initiator;
dest->force_sign_first = src->force_sign_first;
towire_u8(pptr, inflight->locked_scid ? 1 : 0);
if (inflight->locked_scid)
towire_short_channel_id(pptr, *inflight->locked_scid);
}

View File

@ -2,11 +2,14 @@
#define LIGHTNING_CHANNELD_INFLIGHT_H
#include "config.h"
#include <bitcoin/pubkey.h>
#include <bitcoin/tx.h>
#include <common/amount.h>
struct inflight {
/* The new channel outpoint */
struct bitcoin_outpoint outpoint;
struct pubkey remote_funding;
struct amount_sat amnt;
bool remote_tx_sigs;
struct wally_psbt *psbt;
@ -16,12 +19,10 @@ struct inflight {
struct bitcoin_signature last_sig;
bool i_am_initiator;
bool force_sign_first;
bool is_locked;
struct short_channel_id *locked_scid;
};
struct inflight *fromwire_inflight(const tal_t *ctx, const u8 **cursor, size_t *max);
void towire_inflight(u8 **pptr, const struct inflight *inflight);
void copy_inflight(struct inflight *dest, struct inflight *src);
#endif /* LIGHTNING_CHANNELD_INFLIGHT_H */

View File

@ -11,6 +11,7 @@ struct splice_state *splice_state_new(const tal_t *ctx)
splice_state->locked_ready[REMOTE] = false;
splice_state->await_commitment_succcess = false;
splice_state->inflights = NULL;
splice_state->remote_locked_txid = NULL;
return splice_state;
}
@ -31,6 +32,8 @@ struct splicing *splicing_new(const tal_t *ctx)
splicing->received_tx_complete = false;
splicing->sent_tx_complete = false;
splicing->tx_sig_msg = NULL;
splicing->inws = NULL;
splicing->their_sig = NULL;
return splicing;
}

View File

@ -21,6 +21,8 @@ struct splice_state {
bool await_commitment_succcess;
/* The txid of which splice inflight was confirmed */
struct bitcoin_txid locked_txid;
/* The txid our peer locked their splice on */
struct bitcoin_txid *remote_locked_txid;
/* The number of splices that are active (awaiting confirmation) */
u32 count;
};
@ -31,6 +33,8 @@ struct splice_state *splice_state_new(const tal_t *ctx);
/* An active splice negotiation. Born when splice beings and dies when a splice
* negotation has finished */
struct splicing {
/* The remote side's rotated funding pubkey */
struct pubkey remote_funding_pubkey;
/* The opener side's relative balance change */
s64 opener_relative;
/* The accepter side's relative balance change */
@ -53,6 +57,10 @@ struct splicing {
bool sent_tx_complete;
/* If our peer signs early, we allow that and cache it here */
const u8 *tx_sig_msg;
/* The witness stack data received by peer */
struct witness **inws;
/* Their channel funding signature */
struct bitcoin_signature *their_sig;
};
/* Sets `splice` items to default values */

View File

@ -13,6 +13,7 @@ static bool print_superverbose;
#include <ccan/err/err.h>
#include <ccan/str/hex/hex.h>
#include <common/channel_id.h>
#include <common/daemon.h>
#include <common/key_derive.h>
#include <common/setup.h>
#include <common/status.h>
@ -31,6 +32,12 @@ bool fromwire_channel_id(const u8 **cursor UNNEEDED, size_t *max UNNEEDED,
/* Generated stub for fromwire_node_id */
void fromwire_node_id(const u8 **cursor UNNEEDED, size_t *max UNNEEDED, struct node_id *id UNNEEDED)
{ fprintf(stderr, "fromwire_node_id called!\n"); abort(); }
/* Generated stub for pubkey_from_node_id */
bool pubkey_from_node_id(struct pubkey *key UNNEEDED, const struct node_id *id UNNEEDED)
{ fprintf(stderr, "pubkey_from_node_id called!\n"); abort(); }
/* Generated stub for send_backtrace */
void send_backtrace(const char *why UNNEEDED)
{ fprintf(stderr, "send_backtrace called!\n"); abort(); }
/* Generated stub for status_fmt */
void status_fmt(enum log_level level UNNEEDED,
const struct node_id *peer UNNEEDED,
@ -564,7 +571,7 @@ int main(int argc, const char *argv[])
* In the following:
* - *local* transactions are considered, which implies that all
* payments to *local* are delayed.
* - It's assumed that *local* is the funder.
* - It's assumed that *local* is the opener.
* - Private keys are displayed as 32 bytes plus a trailing 1
* (Bitcoin's convention for "compressed" private keys, i.e. keys for
* which the public key is compressed).

View File

@ -1,12 +1,15 @@
#include "config.h"
#include "../../common/blockheight_states.c"
#include "../../common/channel_id.c"
/* Normally fee_states does not allow feerate < 253 */
#define TEST_ALLOW_ZERO_FEERATE 1
#include "../../common/fee_states.c"
#include "../../common/initial_channel.c"
#include "../../common/keyset.c"
#include "../full_channel.c"
#include "../commit_tx.c"
#include <ccan/err/err.h>
#include <common/daemon.h>
#include <common/setup.h>
/* AUTOGENERATED MOCKS START */
@ -22,6 +25,12 @@ void memleak_add_helper_(const tal_t *p UNNEEDED, void (*cb)(struct htable *memt
/* Generated stub for memleak_scan_htable */
void memleak_scan_htable(struct htable *memtable UNNEEDED, const struct htable *ht UNNEEDED)
{ fprintf(stderr, "memleak_scan_htable called!\n"); abort(); }
/* Generated stub for pubkey_from_node_id */
bool pubkey_from_node_id(struct pubkey *key UNNEEDED, const struct node_id *id UNNEEDED)
{ fprintf(stderr, "pubkey_from_node_id called!\n"); abort(); }
/* Generated stub for send_backtrace */
void send_backtrace(const char *why UNNEEDED)
{ fprintf(stderr, "send_backtrace called!\n"); abort(); }
/* Generated stub for status_failed */
void status_failed(enum status_failreason code UNNEEDED,
const char *fmt UNNEEDED, ...)
@ -381,7 +390,7 @@ int main(int argc, const char *argv[])
* In the following:
* - *local* transactions are considered, which implies that all
* payments to *local* are delayed.
* - It's assumed that *local* is the funder.
* - It's assumed that *local* is the opener.
* - Private keys are displayed as 32 bytes plus a trailing 1
* (Bitcoin's convention for "compressed" private keys, i.e. keys for
* which the public key is compressed).
@ -488,7 +497,7 @@ int main(int argc, const char *argv[])
&localbase, &remotebase,
&local_funding_pubkey,
&remote_funding_pubkey,
take(channel_type_none(NULL)), false, LOCAL);
take(channel_type_static_remotekey(NULL)), false, LOCAL);
rchannel = new_full_channel(tmpctx, &cid,
&funding, 0,
take(new_height_states(NULL, REMOTE, &blockheight)),
@ -501,7 +510,7 @@ int main(int argc, const char *argv[])
&remotebase, &localbase,
&remote_funding_pubkey,
&local_funding_pubkey,
take(channel_type_none(NULL)), false, REMOTE);
take(channel_type_static_remotekey(NULL)), false, REMOTE);
/* BOLT #3:
*
@ -509,19 +518,23 @@ int main(int argc, const char *argv[])
*/
local_per_commitment_point = pubkey_from_hex("025f7117a78150fe2ef97db7cfc83bd57b2e2c0d0dd25eaf467a4a1c2a45ce1486");
/* BOLT #3:
* localpubkey: 030d417a46946384f88d5f3337267c5e579765875dc4daca813e21734b140639e7
* remotepubkey: 0394854aa6eab5b2a8122cc726e9dded053a2184d88256816826d6231c068d4a5b
* local_funding_pubkey: 023da092f6980e58d2c037173180e9a465476026ee50f96695963e8efe436f54eb
* remote_funding_pubkey: 030e9f7b623d2ccc7c9bd44d66d5ce21ce504c0acf6385a132cec6d3c39fa711c1
* local_privkey: bb13b121cdc357cd2e608b0aea294afca36e2b34cf958e2e6451a2f27469449101
* local_htlcpubkey: 030d417a46946384f88d5f3337267c5e579765875dc4daca813e21734b140639e7
* remote_htlcpubkey: 0394854aa6eab5b2a8122cc726e9dded053a2184d88256816826d6231c068d4a5b
* local_delayedpubkey: 03fd5960528dc152014952efdb702a88f71e3c1653b2314431701ec77e57fde83c
* local_revocation_pubkey: 0212a140cd0c6539d07cd08dfe09984dec3251ea808b892efeac3ede9402bf2b19
*/
keyset.self_payment_key = pubkey_from_hex("030d417a46946384f88d5f3337267c5e579765875dc4daca813e21734b140639e7");
keyset.other_payment_key = pubkey_from_hex("0394854aa6eab5b2a8122cc726e9dded053a2184d88256816826d6231c068d4a5b");
/* FIXME: Above is wrong for static remotekey! local/remote pubkey are just the basepoints */
keyset.self_payment_key = localbase.payment;
keyset.other_payment_key = remotebase.payment;
keyset.self_delayed_payment_key = pubkey_from_hex("03fd5960528dc152014952efdb702a88f71e3c1653b2314431701ec77e57fde83c");
keyset.self_revocation_key = pubkey_from_hex("0212a140cd0c6539d07cd08dfe09984dec3251ea808b892efeac3ede9402bf2b19");
/* FIXME: Update bolt */
keyset.self_htlc_key = keyset.self_payment_key;
keyset.other_htlc_key = keyset.other_payment_key;
keyset.self_htlc_key = pubkey_from_hex("030d417a46946384f88d5f3337267c5e579765875dc4daca813e21734b140639e7");
keyset.other_htlc_key = pubkey_from_hex("0394854aa6eab5b2a8122cc726e9dded053a2184d88256816826d6231c068d4a5b");
raw_tx = commit_tx(tmpctx,
&funding,
@ -542,7 +555,7 @@ int main(int argc, const char *argv[])
txs = channel_txs(tmpctx, &funding, funding_amount,
&htlc_map, NULL, &funding_wscript_alt,
lchannel, &local_per_commitment_point, 42, LOCAL, 0, 0,
&local_anchor);
&local_anchor, NULL);
assert(tal_count(txs) == 1);
assert(tal_count(htlc_map) == 2);
assert(scripteq(funding_wscript_alt, funding_wscript));
@ -551,7 +564,7 @@ int main(int argc, const char *argv[])
txs2 = channel_txs(tmpctx, &funding, funding_amount,
&htlc_map, NULL, &funding_wscript,
rchannel, &local_per_commitment_point, 42, REMOTE, 0, 0,
&local_anchor);
&local_anchor, NULL);
txs_must_be_eq(txs, txs2);
/* BOLT #3:
@ -580,12 +593,12 @@ int main(int argc, const char *argv[])
txs = channel_txs(tmpctx, &funding, funding_amount,
&htlc_map, NULL, &funding_wscript,
lchannel, &local_per_commitment_point, 42, LOCAL, 0, 0,
&local_anchor);
&local_anchor, NULL);
assert(tal_count(txs) == 1);
txs2 = channel_txs(tmpctx, &funding, funding_amount,
&htlc_map, NULL, &funding_wscript,
rchannel, &local_per_commitment_point, 42, REMOTE, 0, 0,
&local_anchor);
&local_anchor, NULL);
txs_must_be_eq(txs, txs2);
update_feerate(lchannel, feerate_per_kw[LOCAL]);
@ -602,56 +615,56 @@ int main(int argc, const char *argv[])
txs = channel_txs(tmpctx, &funding, funding_amount,
&htlc_map, NULL, &funding_wscript,
lchannel, &local_per_commitment_point, 42, LOCAL, 0, 0,
&local_anchor);
&local_anchor, NULL);
assert(tal_count(txs) == 6);
txs2 = channel_txs(tmpctx, &funding, funding_amount,
&htlc_map, NULL, &funding_wscript,
rchannel, &local_per_commitment_point, 42, REMOTE, 0, 0,
&local_anchor);
&local_anchor, NULL);
txs_must_be_eq(txs, txs2);
/* FIXME: Compare signatures! */
/* BOLT #3:
*
* htlc_success_tx (htlc #0): 020000000001018154ecccf11a5fb56c39654c4deb4d2296f83c69268280b94d021370c94e219700000000000000000001e8030000000000002200204adb4e2f00643db396dd120d4e7dc17625f5f2c11a40d857accc862d6b7dd80e050047304402206a6e59f18764a5bf8d4fa45eebc591566689441229c918b480fb2af8cc6a4aeb02205248f273be447684b33e3c8d1d85a8e0ca9fa0bae9ae33f0527ada9c162919a60147304402207cb324fa0de88f452ffa9389678127ebcf4cabe1dd848b8e076c1a1962bf34720220116ed922b12311bd602d67e60d2529917f21c5b82f25ff6506c0f87886b4dfd5012000000000000000000000000000000000000000000000000000000000000000008a76a91414011f7254d96b819c76986c277d115efce6f7b58763ac67210394854aa6eab5b2a8122cc726e9dded053a2184d88256816826d6231c068d4a5b7c8201208763a914b8bcb07f6344b42ab04250c86a6e8b75d3fdbbc688527c21030d417a46946384f88d5f3337267c5e579765875dc4daca813e21734b140639e752ae677502f401b175ac686800000000
* htlc_success_tx (htlc #0): 02000000000101ab84ff284f162cfbfef241f853b47d4368d171f9e2a1445160cd591c4c7d882b00000000000000000001e8030000000000002200204adb4e2f00643db396dd120d4e7dc17625f5f2c11a40d857accc862d6b7dd80e0500483045022100d9e29616b8f3959f1d3d7f7ce893ffedcdc407717d0de8e37d808c91d3a7c50d022078c3033f6d00095c8720a4bc943c1b45727818c082e4e3ddbc6d3116435b624b014730440220636de5682ef0c5b61f124ec74e8aa2461a69777521d6998295dcea36bc3338110220165285594b23c50b28b82df200234566628a27bcd17f7f14404bd865354eb3ce012000000000000000000000000000000000000000000000000000000000000000008a76a91414011f7254d96b819c76986c277d115efce6f7b58763ac67210394854aa6eab5b2a8122cc726e9dded053a2184d88256816826d6231c068d4a5b7c8201208763a914b8bcb07f6344b42ab04250c86a6e8b75d3fdbbc688527c21030d417a46946384f88d5f3337267c5e579765875dc4daca813e21734b140639e752ae677502f401b175ac686800000000
*/
raw_tx = tx_from_hex(tmpctx, "020000000001018154ecccf11a5fb56c39654c4deb4d2296f83c69268280b94d021370c94e219700000000000000000001e8030000000000002200204adb4e2f00643db396dd120d4e7dc17625f5f2c11a40d857accc862d6b7dd80e050047304402206a6e59f18764a5bf8d4fa45eebc591566689441229c918b480fb2af8cc6a4aeb02205248f273be447684b33e3c8d1d85a8e0ca9fa0bae9ae33f0527ada9c162919a60147304402207cb324fa0de88f452ffa9389678127ebcf4cabe1dd848b8e076c1a1962bf34720220116ed922b12311bd602d67e60d2529917f21c5b82f25ff6506c0f87886b4dfd5012000000000000000000000000000000000000000000000000000000000000000008a76a91414011f7254d96b819c76986c277d115efce6f7b58763ac67210394854aa6eab5b2a8122cc726e9dded053a2184d88256816826d6231c068d4a5b7c8201208763a914b8bcb07f6344b42ab04250c86a6e8b75d3fdbbc688527c21030d417a46946384f88d5f3337267c5e579765875dc4daca813e21734b140639e752ae677502f401b175ac686800000000");
raw_tx = tx_from_hex(tmpctx, "02000000000101ab84ff284f162cfbfef241f853b47d4368d171f9e2a1445160cd591c4c7d882b00000000000000000001e8030000000000002200204adb4e2f00643db396dd120d4e7dc17625f5f2c11a40d857accc862d6b7dd80e0500483045022100d9e29616b8f3959f1d3d7f7ce893ffedcdc407717d0de8e37d808c91d3a7c50d022078c3033f6d00095c8720a4bc943c1b45727818c082e4e3ddbc6d3116435b624b014730440220636de5682ef0c5b61f124ec74e8aa2461a69777521d6998295dcea36bc3338110220165285594b23c50b28b82df200234566628a27bcd17f7f14404bd865354eb3ce012000000000000000000000000000000000000000000000000000000000000000008a76a91414011f7254d96b819c76986c277d115efce6f7b58763ac67210394854aa6eab5b2a8122cc726e9dded053a2184d88256816826d6231c068d4a5b7c8201208763a914b8bcb07f6344b42ab04250c86a6e8b75d3fdbbc688527c21030d417a46946384f88d5f3337267c5e579765875dc4daca813e21734b140639e752ae677502f401b175ac686800000000");
raw_tx->chainparams = chainparams;
bitcoin_tx_input_set_witness(raw_tx, 0, NULL);
tx_must_be_eq(raw_tx, txs[1]);
/* BOLT #3:
*
* htlc_timeout_tx (htlc #2): 020000000001018154ecccf11a5fb56c39654c4deb4d2296f83c69268280b94d021370c94e219701000000000000000001d0070000000000002200204adb4e2f00643db396dd120d4e7dc17625f5f2c11a40d857accc862d6b7dd80e0500483045022100d5275b3619953cb0c3b5aa577f04bc512380e60fa551762ce3d7a1bb7401cff9022037237ab0dac3fe100cde094e82e2bed9ba0ed1bb40154b48e56aa70f259e608b01483045022100c89172099507ff50f4c925e6c5150e871fb6e83dd73ff9fbb72f6ce829a9633f02203a63821d9162e99f9be712a68f9e589483994feae2661e4546cd5b6cec007be501008576a91414011f7254d96b819c76986c277d115efce6f7b58763ac67210394854aa6eab5b2a8122cc726e9dded053a2184d88256816826d6231c068d4a5b7c820120876475527c21030d417a46946384f88d5f3337267c5e579765875dc4daca813e21734b140639e752ae67a914b43e1b38138a41b37f7cd9a1d274bc63e3a9b5d188ac6868f6010000
* htlc_timeout_tx (htlc #2): 02000000000101ab84ff284f162cfbfef241f853b47d4368d171f9e2a1445160cd591c4c7d882b01000000000000000001d0070000000000002200204adb4e2f00643db396dd120d4e7dc17625f5f2c11a40d857accc862d6b7dd80e05004730440220649fe8b20e67e46cbb0d09b4acea87dbec001b39b08dee7bdd0b1f03922a8640022037c462dff79df501cecfdb12ea7f4de91f99230bb544726f6e04527b1f89600401483045022100803159dee7935dba4a1d36a61055ce8fd62caa528573cc221ae288515405a252022029c59e7cffce374fe860100a4a63787e105c3cf5156d40b12dd53ff55ac8cf3f01008576a91414011f7254d96b819c76986c277d115efce6f7b58763ac67210394854aa6eab5b2a8122cc726e9dded053a2184d88256816826d6231c068d4a5b7c820120876475527c21030d417a46946384f88d5f3337267c5e579765875dc4daca813e21734b140639e752ae67a914b43e1b38138a41b37f7cd9a1d274bc63e3a9b5d188ac6868f6010000
*/
raw_tx = tx_from_hex(tmpctx, "020000000001018154ecccf11a5fb56c39654c4deb4d2296f83c69268280b94d021370c94e219701000000000000000001d0070000000000002200204adb4e2f00643db396dd120d4e7dc17625f5f2c11a40d857accc862d6b7dd80e0500483045022100d5275b3619953cb0c3b5aa577f04bc512380e60fa551762ce3d7a1bb7401cff9022037237ab0dac3fe100cde094e82e2bed9ba0ed1bb40154b48e56aa70f259e608b01483045022100c89172099507ff50f4c925e6c5150e871fb6e83dd73ff9fbb72f6ce829a9633f02203a63821d9162e99f9be712a68f9e589483994feae2661e4546cd5b6cec007be501008576a91414011f7254d96b819c76986c277d115efce6f7b58763ac67210394854aa6eab5b2a8122cc726e9dded053a2184d88256816826d6231c068d4a5b7c820120876475527c21030d417a46946384f88d5f3337267c5e579765875dc4daca813e21734b140639e752ae67a914b43e1b38138a41b37f7cd9a1d274bc63e3a9b5d188ac6868f6010000");
raw_tx = tx_from_hex(tmpctx, "02000000000101ab84ff284f162cfbfef241f853b47d4368d171f9e2a1445160cd591c4c7d882b01000000000000000001d0070000000000002200204adb4e2f00643db396dd120d4e7dc17625f5f2c11a40d857accc862d6b7dd80e05004730440220649fe8b20e67e46cbb0d09b4acea87dbec001b39b08dee7bdd0b1f03922a8640022037c462dff79df501cecfdb12ea7f4de91f99230bb544726f6e04527b1f89600401483045022100803159dee7935dba4a1d36a61055ce8fd62caa528573cc221ae288515405a252022029c59e7cffce374fe860100a4a63787e105c3cf5156d40b12dd53ff55ac8cf3f01008576a91414011f7254d96b819c76986c277d115efce6f7b58763ac67210394854aa6eab5b2a8122cc726e9dded053a2184d88256816826d6231c068d4a5b7c820120876475527c21030d417a46946384f88d5f3337267c5e579765875dc4daca813e21734b140639e752ae67a914b43e1b38138a41b37f7cd9a1d274bc63e3a9b5d188ac6868f6010000");
raw_tx->chainparams = chainparams;
bitcoin_tx_input_set_witness(raw_tx, 0, NULL);
tx_must_be_eq(raw_tx, txs[2]);
/* BOLT #3:
*
* htlc_success_tx (htlc #1): 020000000001018154ecccf11a5fb56c39654c4deb4d2296f83c69268280b94d021370c94e219702000000000000000001d0070000000000002200204adb4e2f00643db396dd120d4e7dc17625f5f2c11a40d857accc862d6b7dd80e050047304402201b63ec807771baf4fdff523c644080de17f1da478989308ad13a58b51db91d360220568939d38c9ce295adba15665fa68f51d967e8ed14a007b751540a80b325f20201483045022100def389deab09cee69eaa1ec14d9428770e45bcbe9feb46468ecf481371165c2f022015d2e3c46600b2ebba8dcc899768874cc6851fd1ecb3fffd15db1cc3de7e10da012001010101010101010101010101010101010101010101010101010101010101018a76a91414011f7254d96b819c76986c277d115efce6f7b58763ac67210394854aa6eab5b2a8122cc726e9dded053a2184d88256816826d6231c068d4a5b7c8201208763a9144b6b2e5444c2639cc0fb7bcea5afba3f3cdce23988527c21030d417a46946384f88d5f3337267c5e579765875dc4daca813e21734b140639e752ae677502f501b175ac686800000000
* htlc_success_tx (htlc #1): 02000000000101ab84ff284f162cfbfef241f853b47d4368d171f9e2a1445160cd591c4c7d882b02000000000000000001d0070000000000002200204adb4e2f00643db396dd120d4e7dc17625f5f2c11a40d857accc862d6b7dd80e05004730440220770fc321e97a19f38985f2e7732dd9fe08d16a2efa4bcbc0429400a447faf49102204d40b417f3113e1b0944ae0986f517564ab4acd3d190503faf97a6e420d4335201483045022100a437cc2ce77400ecde441b3398fea3c3ad8bdad8132be818227fe3c5b8345989022069d45e7fa0ae551ec37240845e2c561ceb2567eacf3076a6a43a502d05865faa012001010101010101010101010101010101010101010101010101010101010101018a76a91414011f7254d96b819c76986c277d115efce6f7b58763ac67210394854aa6eab5b2a8122cc726e9dded053a2184d88256816826d6231c068d4a5b7c8201208763a9144b6b2e5444c2639cc0fb7bcea5afba3f3cdce23988527c21030d417a46946384f88d5f3337267c5e579765875dc4daca813e21734b140639e752ae677502f501b175ac686800000000
*/
raw_tx = tx_from_hex(tmpctx, "020000000001018154ecccf11a5fb56c39654c4deb4d2296f83c69268280b94d021370c94e219702000000000000000001d0070000000000002200204adb4e2f00643db396dd120d4e7dc17625f5f2c11a40d857accc862d6b7dd80e050047304402201b63ec807771baf4fdff523c644080de17f1da478989308ad13a58b51db91d360220568939d38c9ce295adba15665fa68f51d967e8ed14a007b751540a80b325f20201483045022100def389deab09cee69eaa1ec14d9428770e45bcbe9feb46468ecf481371165c2f022015d2e3c46600b2ebba8dcc899768874cc6851fd1ecb3fffd15db1cc3de7e10da012001010101010101010101010101010101010101010101010101010101010101018a76a91414011f7254d96b819c76986c277d115efce6f7b58763ac67210394854aa6eab5b2a8122cc726e9dded053a2184d88256816826d6231c068d4a5b7c8201208763a9144b6b2e5444c2639cc0fb7bcea5afba3f3cdce23988527c21030d417a46946384f88d5f3337267c5e579765875dc4daca813e21734b140639e752ae677502f501b175ac686800000000");
raw_tx = tx_from_hex(tmpctx, "02000000000101ab84ff284f162cfbfef241f853b47d4368d171f9e2a1445160cd591c4c7d882b02000000000000000001d0070000000000002200204adb4e2f00643db396dd120d4e7dc17625f5f2c11a40d857accc862d6b7dd80e05004730440220770fc321e97a19f38985f2e7732dd9fe08d16a2efa4bcbc0429400a447faf49102204d40b417f3113e1b0944ae0986f517564ab4acd3d190503faf97a6e420d4335201483045022100a437cc2ce77400ecde441b3398fea3c3ad8bdad8132be818227fe3c5b8345989022069d45e7fa0ae551ec37240845e2c561ceb2567eacf3076a6a43a502d05865faa012001010101010101010101010101010101010101010101010101010101010101018a76a91414011f7254d96b819c76986c277d115efce6f7b58763ac67210394854aa6eab5b2a8122cc726e9dded053a2184d88256816826d6231c068d4a5b7c8201208763a9144b6b2e5444c2639cc0fb7bcea5afba3f3cdce23988527c21030d417a46946384f88d5f3337267c5e579765875dc4daca813e21734b140639e752ae677502f501b175ac686800000000");
raw_tx->chainparams = chainparams;
bitcoin_tx_input_set_witness(raw_tx, 0, NULL);
tx_must_be_eq(raw_tx, txs[3]);
/* BOLT #3:
*
* htlc_timeout_tx (htlc #3): 020000000001018154ecccf11a5fb56c39654c4deb4d2296f83c69268280b94d021370c94e219703000000000000000001b80b0000000000002200204adb4e2f00643db396dd120d4e7dc17625f5f2c11a40d857accc862d6b7dd80e0500483045022100daee1808f9861b6c3ecd14f7b707eca02dd6bdfc714ba2f33bc8cdba507bb182022026654bf8863af77d74f51f4e0b62d461a019561bb12acb120d3f7195d148a554014730440220643aacb19bbb72bd2b635bc3f7375481f5981bace78cdd8319b2988ffcc6704202203d27784ec8ad51ed3bd517a05525a5139bb0b755dd719e0054332d186ac0872701008576a91414011f7254d96b819c76986c277d115efce6f7b58763ac67210394854aa6eab5b2a8122cc726e9dded053a2184d88256816826d6231c068d4a5b7c820120876475527c21030d417a46946384f88d5f3337267c5e579765875dc4daca813e21734b140639e752ae67a9148a486ff2e31d6158bf39e2608864d63fefd09d5b88ac6868f7010000
* htlc_timeout_tx (htlc #3): 02000000000101ab84ff284f162cfbfef241f853b47d4368d171f9e2a1445160cd591c4c7d882b03000000000000000001b80b0000000000002200204adb4e2f00643db396dd120d4e7dc17625f5f2c11a40d857accc862d6b7dd80e050047304402207bcbf4f60a9829b05d2dbab84ed593e0291836be715dc7db6b72a64caf646af802201e489a5a84f7c5cc130398b841d138d031a5137ac8f4c49c770a4959dc3c13630147304402203121d9b9c055f354304b016a36662ee99e1110d9501cb271b087ddb6f382c2c80220549882f3f3b78d9c492de47543cb9a697cecc493174726146536c5954dac748701008576a91414011f7254d96b819c76986c277d115efce6f7b58763ac67210394854aa6eab5b2a8122cc726e9dded053a2184d88256816826d6231c068d4a5b7c820120876475527c21030d417a46946384f88d5f3337267c5e579765875dc4daca813e21734b140639e752ae67a9148a486ff2e31d6158bf39e2608864d63fefd09d5b88ac6868f7010000
*/
raw_tx = tx_from_hex(tmpctx, "020000000001018154ecccf11a5fb56c39654c4deb4d2296f83c69268280b94d021370c94e219703000000000000000001b80b0000000000002200204adb4e2f00643db396dd120d4e7dc17625f5f2c11a40d857accc862d6b7dd80e0500483045022100daee1808f9861b6c3ecd14f7b707eca02dd6bdfc714ba2f33bc8cdba507bb182022026654bf8863af77d74f51f4e0b62d461a019561bb12acb120d3f7195d148a554014730440220643aacb19bbb72bd2b635bc3f7375481f5981bace78cdd8319b2988ffcc6704202203d27784ec8ad51ed3bd517a05525a5139bb0b755dd719e0054332d186ac0872701008576a91414011f7254d96b819c76986c277d115efce6f7b58763ac67210394854aa6eab5b2a8122cc726e9dded053a2184d88256816826d6231c068d4a5b7c820120876475527c21030d417a46946384f88d5f3337267c5e579765875dc4daca813e21734b140639e752ae67a9148a486ff2e31d6158bf39e2608864d63fefd09d5b88ac6868f7010000");
raw_tx = tx_from_hex(tmpctx, "02000000000101ab84ff284f162cfbfef241f853b47d4368d171f9e2a1445160cd591c4c7d882b03000000000000000001b80b0000000000002200204adb4e2f00643db396dd120d4e7dc17625f5f2c11a40d857accc862d6b7dd80e050047304402207bcbf4f60a9829b05d2dbab84ed593e0291836be715dc7db6b72a64caf646af802201e489a5a84f7c5cc130398b841d138d031a5137ac8f4c49c770a4959dc3c13630147304402203121d9b9c055f354304b016a36662ee99e1110d9501cb271b087ddb6f382c2c80220549882f3f3b78d9c492de47543cb9a697cecc493174726146536c5954dac748701008576a91414011f7254d96b819c76986c277d115efce6f7b58763ac67210394854aa6eab5b2a8122cc726e9dded053a2184d88256816826d6231c068d4a5b7c820120876475527c21030d417a46946384f88d5f3337267c5e579765875dc4daca813e21734b140639e752ae67a9148a486ff2e31d6158bf39e2608864d63fefd09d5b88ac6868f7010000");
raw_tx->chainparams = chainparams;
bitcoin_tx_input_set_witness(raw_tx, 0, NULL);
tx_must_be_eq(raw_tx, txs[4]);
/* BOLT #3:
*
* htlc_success_tx (htlc #4): 020000000001018154ecccf11a5fb56c39654c4deb4d2296f83c69268280b94d021370c94e219704000000000000000001a00f0000000000002200204adb4e2f00643db396dd120d4e7dc17625f5f2c11a40d857accc862d6b7dd80e050047304402207e0410e45454b0978a623f36a10626ef17b27d9ad44e2760f98cfa3efb37924f0220220bd8acd43ecaa916a80bd4f919c495a2c58982ce7c8625153f8596692a801d014730440220549e80b4496803cbc4a1d09d46df50109f546d43fbbf86cd90b174b1484acd5402205f12a4f995cb9bded597eabfee195a285986aa6d93ae5bb72507ebc6a4e2349e012004040404040404040404040404040404040404040404040404040404040404048a76a91414011f7254d96b819c76986c277d115efce6f7b58763ac67210394854aa6eab5b2a8122cc726e9dded053a2184d88256816826d6231c068d4a5b7c8201208763a91418bc1a114ccf9c052d3d23e28d3b0a9d1227434288527c21030d417a46946384f88d5f3337267c5e579765875dc4daca813e21734b140639e752ae677502f801b175ac686800000000
* htlc_success_tx (htlc #4): 02000000000101ab84ff284f162cfbfef241f853b47d4368d171f9e2a1445160cd591c4c7d882b04000000000000000001a00f0000000000002200204adb4e2f00643db396dd120d4e7dc17625f5f2c11a40d857accc862d6b7dd80e0500473044022076dca5cb81ba7e466e349b7128cdba216d4d01659e29b96025b9524aaf0d1899022060de85697b88b21c749702b7d2cfa7dfeaa1f472c8f1d7d9c23f2bf968464b8701483045022100d9080f103cc92bac15ec42464a95f070c7fb6925014e673ee2ea1374d36a7f7502200c65294d22eb20d48564954d5afe04a385551919d8b2ddb4ae2459daaeee1d95012004040404040404040404040404040404040404040404040404040404040404048a76a91414011f7254d96b819c76986c277d115efce6f7b58763ac67210394854aa6eab5b2a8122cc726e9dded053a2184d88256816826d6231c068d4a5b7c8201208763a91418bc1a114ccf9c052d3d23e28d3b0a9d1227434288527c21030d417a46946384f88d5f3337267c5e579765875dc4daca813e21734b140639e752ae677502f801b175ac686800000000
*/
raw_tx = tx_from_hex(tmpctx, "020000000001018154ecccf11a5fb56c39654c4deb4d2296f83c69268280b94d021370c94e219704000000000000000001a00f0000000000002200204adb4e2f00643db396dd120d4e7dc17625f5f2c11a40d857accc862d6b7dd80e050047304402207e0410e45454b0978a623f36a10626ef17b27d9ad44e2760f98cfa3efb37924f0220220bd8acd43ecaa916a80bd4f919c495a2c58982ce7c8625153f8596692a801d014730440220549e80b4496803cbc4a1d09d46df50109f546d43fbbf86cd90b174b1484acd5402205f12a4f995cb9bded597eabfee195a285986aa6d93ae5bb72507ebc6a4e2349e012004040404040404040404040404040404040404040404040404040404040404048a76a91414011f7254d96b819c76986c277d115efce6f7b58763ac67210394854aa6eab5b2a8122cc726e9dded053a2184d88256816826d6231c068d4a5b7c8201208763a91418bc1a114ccf9c052d3d23e28d3b0a9d1227434288527c21030d417a46946384f88d5f3337267c5e579765875dc4daca813e21734b140639e752ae677502f801b175ac686800000000");
raw_tx = tx_from_hex(tmpctx, "02000000000101ab84ff284f162cfbfef241f853b47d4368d171f9e2a1445160cd591c4c7d882b04000000000000000001a00f0000000000002200204adb4e2f00643db396dd120d4e7dc17625f5f2c11a40d857accc862d6b7dd80e0500473044022076dca5cb81ba7e466e349b7128cdba216d4d01659e29b96025b9524aaf0d1899022060de85697b88b21c749702b7d2cfa7dfeaa1f472c8f1d7d9c23f2bf968464b8701483045022100d9080f103cc92bac15ec42464a95f070c7fb6925014e673ee2ea1374d36a7f7502200c65294d22eb20d48564954d5afe04a385551919d8b2ddb4ae2459daaeee1d95012004040404040404040404040404040404040404040404040404040404040404048a76a91414011f7254d96b819c76986c277d115efce6f7b58763ac67210394854aa6eab5b2a8122cc726e9dded053a2184d88256816826d6231c068d4a5b7c8201208763a91418bc1a114ccf9c052d3d23e28d3b0a9d1227434288527c21030d417a46946384f88d5f3337267c5e579765875dc4daca813e21734b140639e752ae677502f801b175ac686800000000");
raw_tx->chainparams = chainparams;
bitcoin_tx_input_set_witness(raw_tx, 0, NULL);
tx_must_be_eq(raw_tx, txs[5]);
@ -682,14 +695,14 @@ int main(int argc, const char *argv[])
&htlc_map, NULL, &funding_wscript,
lchannel, &local_per_commitment_point, 42,
LOCAL, 0, 0,
&local_anchor);
&local_anchor, NULL);
tx_must_be_eq(txs[0], raw_tx);
txs2 = channel_txs(tmpctx, &funding, funding_amount,
&htlc_map, NULL, &funding_wscript,
rchannel, &local_per_commitment_point,
42, REMOTE, 0, 0,
&local_anchor);
&local_anchor, NULL);
txs_must_be_eq(txs, txs2);
}

View File

@ -179,13 +179,9 @@ static void human_help(char *buffer, const jsmntok_t *result)
unsigned int i;
/* `curr` is used as a temporary token */
const jsmntok_t *curr;
const char *prev_cat;
/* Contains all commands objects, which have the following structure :
* {
* "command": "The command name and usage",
* "category": "The command category",
* "description": "The command's description",
* "verbose": "The command's detailed description"
* "command": "The command name and usage"
* }
*/
const jsmntok_t * help_array = json_get_member(buffer, result, "help");
@ -198,22 +194,11 @@ static void human_help(char *buffer, const jsmntok_t *result)
asort(help, tal_count(help), compare_help, buffer);
prev_cat = "";
for (i = 0; i < tal_count(help); i++) {
const jsmntok_t *category, *command, *desc;
category = json_get_member(buffer, help[i], "category");
if (category && !json_tok_streq(buffer, category, prev_cat)) {
prev_cat = json_strdup(help, buffer, category);
printf("=== %s ===\n\n", prev_cat);
}
const jsmntok_t *command;
command = json_get_member(buffer, help[i], "command");
desc = json_get_member(buffer, help[i], "description");
printf("%.*s\n",
command->end - command->start, buffer + command->start);
printf(" %.*s\n\n",
desc->end - desc->start, buffer + desc->start);
human_readable(buffer, command, '\n');
printf("\n");
}
tal_free(help);
@ -309,7 +294,7 @@ try_exec_man (const char *page, char *relative_to) {
case 0:
/* child, run man command. */
if (relative_to != NULL) {
page = tal_fmt(page, "%s/../doc/%s.7", relative_to, page);
page = tal_fmt(page, "%s/%s.7", relative_to, page);
execlp("man", "man", "-l", page, (char *)NULL);
}
else {
@ -716,12 +701,18 @@ int main(int argc, char *argv[])
command = argv[2];
char *page = tal_fmt(ctx, "lightning-%s", command);
/* Try to find the page in the MANPATH and PATH. */
try_exec_man(page, NULL);
/* Try to find the page relative to this executable.
* This handles the common scenario where lightning-cli
* was built from source and hasn't been installed yet */
try_exec_man(page, dirname(argv[0]));
const char *dir = dirname(argv[0]);
try_exec_man(page, tal_fmt(page, "%s/../doc", dir));
/* Try to find the page relative to this executable, but in the
* install directory hierarchy. */
try_exec_man(page, tal_fmt(page, "%s/../share/man/man7", dir));
tal_free(page);
}
@ -875,10 +866,8 @@ int main(int argc, char *argv[])
default:
if (handle_notify(resp, toks, notification_level,
&last_was_progress)) {
/* +2 for \n\n */
size_t len = toks[0].end - toks[0].start + 2;
memmove(resp, resp + len, off - len);
off -= len;
memmove(resp, resp + toks[0].end, off - toks[0].end);
off -= toks[0].end;
jsmn_init(&parser);
toks[0].type = JSMN_UNDEFINED;
/* Don't force another read! */

View File

@ -4,6 +4,7 @@
#include <common/bigsize.h>
#include <common/channel_id.h>
#include <common/configvar.h>
#include <common/daemon.h>
#include <common/json_stream.h>
#include <common/node_id.h>
#include <common/setup.h>
@ -89,6 +90,12 @@ const char *log_level_name(enum log_level level UNNEEDED)
bool log_level_parse(const char *levelstr UNNEEDED, size_t len UNNEEDED,
enum log_level *level UNNEEDED)
{ fprintf(stderr, "log_level_parse called!\n"); abort(); }
/* Generated stub for pubkey_from_node_id */
bool pubkey_from_node_id(struct pubkey *key UNNEEDED, const struct node_id *id UNNEEDED)
{ fprintf(stderr, "pubkey_from_node_id called!\n"); abort(); }
/* Generated stub for send_backtrace */
void send_backtrace(const char *why UNNEEDED)
{ fprintf(stderr, "send_backtrace called!\n"); abort(); }
/* Generated stub for towire_amount_msat */
void towire_amount_msat(u8 **pptr UNNEEDED, const struct amount_msat msat UNNEEDED)
{ fprintf(stderr, "towire_amount_msat called!\n"); abort(); }

View File

@ -4,6 +4,7 @@
#include <common/bigsize.h>
#include <common/channel_id.h>
#include <common/configvar.h>
#include <common/daemon.h>
#include <common/json_stream.h>
#include <common/node_id.h>
#include <common/setup.h>
@ -89,6 +90,12 @@ const char *log_level_name(enum log_level level UNNEEDED)
bool log_level_parse(const char *levelstr UNNEEDED, size_t len UNNEEDED,
enum log_level *level UNNEEDED)
{ fprintf(stderr, "log_level_parse called!\n"); abort(); }
/* Generated stub for pubkey_from_node_id */
bool pubkey_from_node_id(struct pubkey *key UNNEEDED, const struct node_id *id UNNEEDED)
{ fprintf(stderr, "pubkey_from_node_id called!\n"); abort(); }
/* Generated stub for send_backtrace */
void send_backtrace(const char *why UNNEEDED)
{ fprintf(stderr, "send_backtrace called!\n"); abort(); }
/* Generated stub for towire_amount_msat */
void towire_amount_msat(u8 **pptr UNNEEDED, const struct amount_msat msat UNNEEDED)
{ fprintf(stderr, "towire_amount_msat called!\n"); abort(); }

View File

@ -4,6 +4,7 @@
#include <common/bigsize.h>
#include <common/channel_id.h>
#include <common/configvar.h>
#include <common/daemon.h>
#include <common/json_stream.h>
#include <common/node_id.h>
#include <common/setup.h>
@ -92,6 +93,12 @@ const char *log_level_name(enum log_level level UNNEEDED)
bool log_level_parse(const char *levelstr UNNEEDED, size_t len UNNEEDED,
enum log_level *level UNNEEDED)
{ fprintf(stderr, "log_level_parse called!\n"); abort(); }
/* Generated stub for pubkey_from_node_id */
bool pubkey_from_node_id(struct pubkey *key UNNEEDED, const struct node_id *id UNNEEDED)
{ fprintf(stderr, "pubkey_from_node_id called!\n"); abort(); }
/* Generated stub for send_backtrace */
void send_backtrace(const char *why UNNEEDED)
{ fprintf(stderr, "send_backtrace called!\n"); abort(); }
/* Generated stub for towire_amount_msat */
void towire_amount_msat(u8 **pptr UNNEEDED, const struct amount_msat msat UNNEEDED)
{ fprintf(stderr, "towire_amount_msat called!\n"); abort(); }

View File

@ -1,6 +1,6 @@
[package]
name = "cln-grpc"
version = "0.1.8"
version = "0.4.1"
edition = "2021"
license = "MIT"
description = "The Core Lightning API as grpc primitives. Provides the bindings used to expose the API over the network."
@ -15,16 +15,21 @@ server = ["cln-rpc"]
[dependencies]
anyhow = "1.0"
log = "0.4"
cln-rpc = { path="../cln-rpc/", version = "^0.1", optional = true }
tonic = { version = "0.8", features = ["tls", "transport"] }
prost = "0.11"
cln-rpc = { path = "../cln-rpc/", version = "0.4", optional = true }
cfg-if = "1.0"
serde = { version = "1.0", features = ["derive"] }
tonic = { version = "0.11", features = ["tls", "transport"] }
prost = "0.12"
hex = "0.4.3"
bitcoin = { version = "0.30", features = [ "serde" ] }
bitcoin = { version = "0.31", features = ["serde"] }
tokio-stream = { version = "0.1.14", features = ["sync"] }
tokio = { version = "1.36.0", features = ["sync"] }
futures-core = "0.3.30"
tokio-util = "0.7.10"
[dev-dependencies]
serde_json = "1.0.72"
cln-rpc = { path="../cln-rpc/", version = "^0.1" }
cln-rpc = { path = "../cln-rpc/", version = "0.4" }
[build-dependencies]
tonic-build = "0.8"
tonic-build = "0.11"

Binary file not shown.

View File

@ -37,6 +37,8 @@ enum ChannelState {
DualopendOpenInit = 9;
DualopendAwaitingLockin = 10;
ChanneldAwaitingSplice = 11;
DualopendOpenCommitted = 12;
DualopendOpenCommittReady = 13;
}
enum HtlcState {
@ -62,8 +64,6 @@ enum HtlcState {
SentRemoveAckRevocation = 19;
}
message ChannelStateChangeCause {}
message Outpoint {
bytes txid = 1;
uint32 outnum = 2;
@ -86,9 +86,9 @@ message OutputDesc {
message RouteHop {
bytes id = 1;
string short_channel_id = 2;
string scid = 2;
Amount feebase = 3;
uint32 feeprop = 4;
uint32 feeprop = 4;
uint32 expirydelta = 5;
}
message Routehint {
@ -98,6 +98,19 @@ message RoutehintList {
repeated Routehint hints = 2;
}
message DecodeRouteHop {
bytes pubkey = 1;
string short_channel_id = 2;
Amount fee_base_msat = 3;
uint32 fee_proportional_millionths = 4;
uint32 cltv_expiry_delta = 5;
}
message DecodeRoutehint {
repeated DecodeRouteHop hops = 1;
}
message DecodeRoutehintList {
repeated DecodeRoutehint hints = 2;
}
message TlvEntry {
uint64 type = 1;
@ -114,4 +127,22 @@ enum ChannelTypeName {
anchors_zero_fee_htlc_tx_even = 2;
scid_alias_even = 3;
zeroconf_even = 4;
anchors_even = 5;
}
enum AutocleanSubsystem {
SUCCEEDEDFORWARDS = 0;
FAILEDFORWARDS = 1;
SUCCEEDEDPAYS = 2;
FAILEDPAYS = 3;
PAIDINVOICES = 4;
EXPIREDINVOICES = 5;
}
enum PluginSubcommand {
START = 0;
STOP = 1;
RESCAN = 2;
STARTDIR = 3;
LIST = 4;
}

BIN
cln-grpc/src/convert.rs generated

Binary file not shown.

View File

@ -1,15 +1,16 @@
// Huge json!() macros require lots of recursion
#![recursion_limit = "1024"]
#[cfg(feature = "server")]
mod convert;
pub mod pb;
#[cfg(feature = "server")]
mod server;
#[cfg(feature = "server")]
pub use crate::server::Server;
cfg_if::cfg_if! {
if #[cfg(feature = "server")] {
mod convert;
mod server;
pub use server::Server;
pub use server::NotificationStream;
}
}
#[cfg(test)]
mod test;

View File

@ -136,7 +136,7 @@ mod convert {
fn from(c: RouteHop) -> Self {
Self {
id: cln_rpc::primitives::PublicKey::from_slice(&c.id).unwrap(),
scid: cln_rpc::primitives::ShortChannelId::from_str(&c.short_channel_id).unwrap(),
scid: cln_rpc::primitives::ShortChannelId::from_str(&c.scid).unwrap(),
feebase: c.feebase.unwrap().into(),
feeprop: c.feeprop,
expirydelta: c.expirydelta as u16,
@ -167,7 +167,7 @@ mod convert {
feebase: Some(c.feebase.into()),
feeprop: c.feeprop,
expirydelta: c.expirydelta as u32,
short_channel_id: c.scid.to_string(),
scid: c.scid.to_string(),
}
}
}
@ -188,6 +188,65 @@ mod convert {
}
}
impl From<DecodeRouteHop> for cln_rpc::primitives::DecodeRoutehop {
fn from(c: DecodeRouteHop) -> Self {
Self {
pubkey: cln_rpc::primitives::PublicKey::from_slice(&c.pubkey).unwrap(),
short_channel_id: cln_rpc::primitives::ShortChannelId::from_str(
&c.short_channel_id,
)
.unwrap(),
fee_base_msat: c.fee_base_msat.unwrap().into(),
fee_proportional_millionths: c.fee_proportional_millionths,
cltv_expiry_delta: c.cltv_expiry_delta as u16,
}
}
}
impl From<DecodeRoutehint> for cln_rpc::primitives::DecodeRoutehint {
fn from(c: DecodeRoutehint) -> Self {
Self {
hops: c.hops.into_iter().map(|h| h.into()).collect(),
}
}
}
impl From<DecodeRoutehintList> for cln_rpc::primitives::DecodeRoutehintList {
fn from(c: DecodeRoutehintList) -> Self {
Self {
hints: c.hints.into_iter().map(|h| h.into()).collect(),
}
}
}
impl From<cln_rpc::primitives::DecodeRoutehop> for DecodeRouteHop {
fn from(c: cln_rpc::primitives::DecodeRoutehop) -> Self {
Self {
pubkey: c.pubkey.serialize().to_vec(),
fee_base_msat: Some(c.fee_base_msat.into()),
fee_proportional_millionths: c.fee_proportional_millionths,
cltv_expiry_delta: c.cltv_expiry_delta as u32,
short_channel_id: c.short_channel_id.to_string(),
}
}
}
impl From<cln_rpc::primitives::DecodeRoutehint> for DecodeRoutehint {
fn from(c: cln_rpc::primitives::DecodeRoutehint) -> Self {
Self {
hops: c.hops.into_iter().map(|h| h.into()).collect(),
}
}
}
impl From<cln_rpc::primitives::DecodeRoutehintList> for DecodeRoutehintList {
fn from(c: cln_rpc::primitives::DecodeRoutehintList) -> Self {
Self {
hints: c.hints.into_iter().map(|e| e.into()).collect(),
}
}
}
impl From<TlvStream> for cln_rpc::primitives::TlvStream {
fn from(s: TlvStream) -> Self {
Self {

File diff suppressed because it is too large Load Diff

View File

@ -276,7 +276,7 @@ fn test_keysend() {
"035d2b1192dfba134e10e540875d366ebc8bc353d5aa766b80c090b39c3a5d885d",
)
.unwrap(),
short_channel_id: "12345x678x90".to_string(),
scid: "12345x678x90".to_string(),
feebase: Some(Amount { msat: 123 }),
feeprop: 1234,
expirydelta: 9,
@ -285,7 +285,7 @@ fn test_keysend() {
"035d2b1192dfba134e10e540875d366ebc8bc353d5aa766b80c090b39c3a5d885d",
)
.unwrap(),
short_channel_id: "12345x678x90".to_string(),
scid: "12345x678x90".to_string(),
feebase: Some(Amount { msat: 123 }),
feeprop: 1234,
expirydelta: 9,
@ -293,6 +293,7 @@ fn test_keysend() {
}],
}),
extratlvs: None,
maxfee: None
};
let u: cln_rpc::model::requests::KeysendRequest = g.into();

View File

@ -1,6 +1,6 @@
[package]
name = "cln-rpc"
version = "0.1.8"
version = "0.4.0"
edition = "2021"
license = "MIT"
description = "An async RPC client for Core Lightning."
@ -14,7 +14,7 @@ path = "examples/getinfo.rs"
[dependencies]
anyhow = "1.0"
bitcoin = { version = "0.30", features = [ "serde" ] }
bitcoin = { version = "0.31", features = [ "serde" ] }
bytes = "1"
futures-util = { version = "0.3", features = [ "sink" ] }
hex = "0.4.3"

View File

@ -2,7 +2,7 @@ cln-rpc-wrongdir:
$(MAKE) -C .. cln-rpc-all
CLN_RPC_EXAMPLES := target/${RUST_PROFILE}/examples/cln-rpc-getinfo
CLN_RPC_GENALL = cln-rpc/src/model.rs
CLN_RPC_GENALL = cln-rpc/src/model.rs cln-rpc/src/notifications.rs
CLN_RPC_SOURCES = $(shell find cln-rpc -name *.rs) ${CLN_RPC_GENALL}
DEFAULT_TARGETS += $(CLN_RPC_EXAMPLES) $(CLN_RPC_GENALL)
@ -18,4 +18,4 @@ target/${RUST_PROFILE}/examples/cln-plugin-reentrant: ${CLN_RPC_SOURCES} plugins
cargo build ${CARGO_OPTS} --example cln-plugin-reentrant
cln-rpc-all: ${CLN_RPC_GEN_ALL} ${CLN_RPC_EXAMPLES}
cln-rpc-all: ${CLN_RPC_GENALL} ${CLN_RPC_EXAMPLES}

View File

@ -105,6 +105,7 @@ impl Decoder for JsonCodec {
/// A codec that reads fully formed [crate::messages::JsonRpc]
/// messages. Internally it uses the [JsonCodec] which itself is built
/// on the [MultiLineCodec].
#[allow(dead_code)]
#[derive(Default)]
pub(crate) struct JsonRpcCodec {
inner: JsonCodec,

View File

@ -331,6 +331,8 @@ where
#[cfg(test)]
mod test {
use self::notifications::{BlockAddedNotification, CustomMsgNotification};
use super::*;
use crate::model::*;
use crate::primitives::PublicKey;
@ -553,4 +555,64 @@ mod test {
assert_eq!(rpc_error.code.unwrap(), 666);
assert_eq!(rpc_error.message, "MOCK_ERROR");
}
#[test]
fn serialize_custom_msg_notification() {
let msg = CustomMsgNotification {
peer_id : PublicKey::from_str("0364aeb75519be29d1af7b8cc6232dbda9fdabb79b66e4e1f6a223750954db210b").unwrap(),
payload : String::from("941746573749")
};
let notification = Notification::CustomMsg(msg);
assert_eq!(
serde_json::to_value(notification).unwrap(),
serde_json::json!(
{
"custommsg" : {
"peer_id" : "0364aeb75519be29d1af7b8cc6232dbda9fdabb79b66e4e1f6a223750954db210b",
"payload" : "941746573749"
}
}
)
);
}
#[test]
fn serialize_block_added_notification() {
let block_added = BlockAddedNotification {
hash : crate::primitives::Sha256::from_str("000000000000000000000acab8abe0c67a52ed7e5a90a19c64930ff11fa84eca").unwrap(),
height : 830702
};
let notification = Notification::BlockAdded(block_added);
assert_eq!(
serde_json::to_value(notification).unwrap(),
serde_json::json!({
"block_added" : {
"hash" : "000000000000000000000acab8abe0c67a52ed7e5a90a19c64930ff11fa84eca",
"height" : 830702
}
})
)
}
#[test]
fn deserialize_connect_notification() {
let connect_json = serde_json::json!({
"connect" : {
"address" : {
"address" : "127.0.0.1",
"port" : 38012,
"type" : "ipv4"
},
"direction" : "in",
"id" : "022d223620a359a47ff7f7ac447c85c46c923da53389221a0054c11c1e3ca31d59"
}
});
let _ : Notification = serde_json::from_value(connect_json).unwrap();
}
}

BIN
cln-rpc/src/model.rs generated

Binary file not shown.

View File

@ -1,4 +1,231 @@
use serde::{Deserialize, Serialize};
// This file is autogenerated by `msggen`
// Do not edit it manually, your changes will be overwritten
#[derive(Debug, Deserialize, Serialize)]
pub enum Notification {}
use crate::primitives::*;
use serde::{Serialize, Deserialize};
#[derive(Clone, Debug, Deserialize, Serialize)]
pub enum Notification {
#[serde(rename = "block_added")]
BlockAdded(BlockAddedNotification),
#[serde(rename = "channel_open_failed")]
ChannelOpenFailed(ChannelOpenFailedNotification),
#[serde(rename = "channel_opened")]
ChannelOpened(ChannelOpenedNotification),
#[serde(rename = "connect")]
Connect(ConnectNotification),
#[serde(rename = "custommsg")]
CustomMsg(CustomMsgNotification),
#[serde(rename = "channel_state_changed")]
ChannelStateChanged(ChannelStateChangedNotification),
}
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct BlockAddedNotification {
pub hash: Sha256,
pub height: u32,
}
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct ChannelOpenFailedNotification {
pub channel_id: Sha256,
}
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct ChannelOpenedNotification {
pub channel_ready: bool,
pub funding_msat: Amount,
pub funding_txid: String,
pub id: PublicKey,
}
/// ['Direction of the connection']
#[derive(Copy, Clone, Debug, Deserialize, Serialize, PartialEq, Eq)]
#[allow(non_camel_case_types)]
pub enum ConnectDirection {
#[serde(rename = "in")]
IN = 0,
#[serde(rename = "out")]
OUT = 1,
}
impl TryFrom<i32> for ConnectDirection {
type Error = anyhow::Error;
fn try_from(c: i32) -> Result<ConnectDirection, anyhow::Error> {
match c {
0 => Ok(ConnectDirection::IN),
1 => Ok(ConnectDirection::OUT),
o => Err(anyhow::anyhow!("Unknown variant {} for enum ConnectDirection", o)),
}
}
}
impl ToString for ConnectDirection {
fn to_string(&self) -> String {
match self {
ConnectDirection::IN => "IN",
ConnectDirection::OUT => "OUT",
}.to_string()
}
}
/// ['Type of connection (*torv2*/*torv3* only if **direction** is *out*)']
#[derive(Copy, Clone, Debug, Deserialize, Serialize, PartialEq, Eq)]
#[allow(non_camel_case_types)]
pub enum ConnectAddressType {
#[serde(rename = "local socket")]
LOCAL_SOCKET = 0,
#[serde(rename = "ipv4")]
IPV4 = 1,
#[serde(rename = "ipv6")]
IPV6 = 2,
#[serde(rename = "torv2")]
TORV2 = 3,
#[serde(rename = "torv3")]
TORV3 = 4,
}
impl TryFrom<i32> for ConnectAddressType {
type Error = anyhow::Error;
fn try_from(c: i32) -> Result<ConnectAddressType, anyhow::Error> {
match c {
0 => Ok(ConnectAddressType::LOCAL_SOCKET),
1 => Ok(ConnectAddressType::IPV4),
2 => Ok(ConnectAddressType::IPV6),
3 => Ok(ConnectAddressType::TORV2),
4 => Ok(ConnectAddressType::TORV3),
o => Err(anyhow::anyhow!("Unknown variant {} for enum ConnectAddressType", o)),
}
}
}
impl ToString for ConnectAddressType {
fn to_string(&self) -> String {
match self {
ConnectAddressType::LOCAL_SOCKET => "LOCAL_SOCKET",
ConnectAddressType::IPV4 => "IPV4",
ConnectAddressType::IPV6 => "IPV6",
ConnectAddressType::TORV2 => "TORV2",
ConnectAddressType::TORV3 => "TORV3",
}.to_string()
}
}
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct ConnectAddress {
#[serde(skip_serializing_if = "Option::is_none")]
pub address: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub port: Option<u16>,
#[serde(skip_serializing_if = "Option::is_none")]
pub socket: Option<String>,
// Path `connect.address.type`
#[serde(rename = "type")]
pub item_type: ConnectAddressType,
}
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct ConnectNotification {
// Path `connect.direction`
pub direction: ConnectDirection,
pub address: ConnectAddress,
pub id: PublicKey,
}
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct CustomMsgNotification {
pub payload: String,
pub peer_id: PublicKey,
}
/// ['The cause of the state change.']
#[derive(Copy, Clone, Debug, Deserialize, Serialize, PartialEq, Eq)]
#[allow(non_camel_case_types)]
pub enum ChannelStateChangedCause {
#[serde(rename = "unknown")]
UNKNOWN = 0,
#[serde(rename = "local")]
LOCAL = 1,
#[serde(rename = "user")]
USER = 2,
#[serde(rename = "remote")]
REMOTE = 3,
#[serde(rename = "protocol")]
PROTOCOL = 4,
#[serde(rename = "onchain")]
ONCHAIN = 5,
}
impl TryFrom<i32> for ChannelStateChangedCause {
type Error = anyhow::Error;
fn try_from(c: i32) -> Result<ChannelStateChangedCause, anyhow::Error> {
match c {
0 => Ok(ChannelStateChangedCause::UNKNOWN),
1 => Ok(ChannelStateChangedCause::LOCAL),
2 => Ok(ChannelStateChangedCause::USER),
3 => Ok(ChannelStateChangedCause::REMOTE),
4 => Ok(ChannelStateChangedCause::PROTOCOL),
5 => Ok(ChannelStateChangedCause::ONCHAIN),
o => Err(anyhow::anyhow!("Unknown variant {} for enum ChannelStateChangedCause", o)),
}
}
}
impl ToString for ChannelStateChangedCause {
fn to_string(&self) -> String {
match self {
ChannelStateChangedCause::UNKNOWN => "UNKNOWN",
ChannelStateChangedCause::LOCAL => "LOCAL",
ChannelStateChangedCause::USER => "USER",
ChannelStateChangedCause::REMOTE => "REMOTE",
ChannelStateChangedCause::PROTOCOL => "PROTOCOL",
ChannelStateChangedCause::ONCHAIN => "ONCHAIN",
}.to_string()
}
}
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct ChannelStateChangedNotification {
#[serde(skip_serializing_if = "Option::is_none")]
pub old_state: Option<ChannelState>,
// Path `channel_state_changed.cause`
pub cause: ChannelStateChangedCause,
// Path `channel_state_changed.new_state`
pub new_state: ChannelState,
pub channel_id: Sha256,
pub message: String,
pub peer_id: PublicKey,
pub short_channel_id: ShortChannelId,
pub timestamp: String,
}
pub mod requests{
use serde::{Serialize, Deserialize};
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct StreamBlockAddedRequest {
}
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct StreamChannelOpenFailedRequest {
}
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct StreamChannelOpenedRequest {
}
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct StreamConnectRequest {
}
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct StreamCustomMsgRequest {
}
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct StreamChannelStateChangedRequest {
}
}

View File

@ -12,7 +12,7 @@ use std::string::ToString;
pub use bitcoin::hashes::sha256::Hash as Sha256;
pub use bitcoin::secp256k1::PublicKey;
#[derive(Copy, Clone, Serialize, Deserialize, Debug, PartialEq)]
#[derive(Copy, Clone, Serialize, Deserialize, Debug, PartialEq, Eq)]
#[allow(non_camel_case_types)]
pub enum ChannelState {
OPENINGD = 0,
@ -27,9 +27,11 @@ pub enum ChannelState {
DUALOPEND_OPEN_INIT = 9,
DUALOPEND_AWAITING_LOCKIN = 10,
CHANNELD_AWAITING_SPLICE = 11,
DUALOPEND_OPEN_COMMITTED = 12,
DUALOPEND_OPEN_COMMIT_READY = 13,
}
#[derive(Copy, Clone, Serialize, Deserialize, Debug)]
#[derive(Copy, Clone, Serialize, Deserialize, Debug, PartialEq, Eq)]
#[allow(non_camel_case_types)]
pub enum HtlcState {
SENT_ADD_HTLC = 0,
@ -67,18 +69,71 @@ pub enum ChannelTypeName {
SCID_ALIAS_EVEN = 3,
#[serde(rename = "zeroconf/even")]
ZEROCONF_EVEN = 4,
#[serde(rename = "anchors/even")]
ANCHORS_EVEN = 5,
}
#[derive(Copy, Clone, Serialize, Deserialize, Debug)]
#[allow(non_camel_case_types)]
#[serde(rename_all = "lowercase")]
pub enum ChannelStateChangeCause {
UNKNOWN,
LOCAL,
USER,
REMOTE,
PROTOCOL,
ONCHAIN,
pub enum AutocleanSubsystem {
#[serde(rename = "succeededforwards")]
SUCCEEDEDFORWARDS = 0,
#[serde(rename = "failedforwards")]
FAILEDFORWARDS = 1,
#[serde(rename = "succeededpays")]
SUCCEEDEDPAYS = 2,
#[serde(rename = "failedpays")]
FAILEDPAYS = 3,
#[serde(rename = "paidinvoices")]
PAIDINVOICES = 4,
#[serde(rename = "expiredinvoices")]
EXPIREDINVOICES = 5,
}
impl TryFrom<i32> for AutocleanSubsystem {
type Error = crate::Error;
fn try_from(value: i32) -> std::result::Result<Self, Self::Error> {
match value {
0 => Ok(AutocleanSubsystem::SUCCEEDEDFORWARDS),
1 => Ok(AutocleanSubsystem::FAILEDFORWARDS),
2 => Ok(AutocleanSubsystem::SUCCEEDEDPAYS),
3 => Ok(AutocleanSubsystem::FAILEDPAYS),
4 => Ok(AutocleanSubsystem::PAIDINVOICES),
5 => Ok(AutocleanSubsystem::EXPIREDINVOICES),
_ => Err(anyhow!("Invalid AutocleanSubsystem {}", value)),
}
}
}
#[derive(Copy, Clone, Serialize, Deserialize, Debug)]
#[allow(non_camel_case_types)]
pub enum PluginSubcommand {
#[serde(rename = "start")]
START = 0,
#[serde(rename = "stop")]
STOP = 1,
#[serde(rename = "rescan")]
RESCAN = 2,
#[serde(rename = "startdir")]
STARTDIR = 3,
#[serde(rename = "list")]
LIST = 4,
}
impl TryFrom<i32> for PluginSubcommand {
type Error = crate::Error;
fn try_from(value: i32) -> std::result::Result<Self, Self::Error> {
match value {
0 => Ok(PluginSubcommand::START),
1 => Ok(PluginSubcommand::STOP),
2 => Ok(PluginSubcommand::RESCAN),
3 => Ok(PluginSubcommand::STARTDIR),
4 => Ok(PluginSubcommand::LIST),
_ => Err(anyhow!("Invalid PluginSubcommand mapping!")),
}
}
}
/// An `Amount` that can also be `any`. Useful for cases in which you
@ -182,6 +237,11 @@ impl FromStr for ShortChannelId {
))
}
}
impl From<u64> for ShortChannelId {
fn from(scid: u64) -> Self {
ShortChannelId(scid)
}
}
impl Display for ShortChannelId {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
write!(f, "{}x{}x{}", self.block(), self.txindex(), self.outnum())
@ -197,6 +257,63 @@ impl ShortChannelId {
pub fn outnum(&self) -> u16 {
self.0 as u16 & 0xFFFF
}
pub fn to_u64(&self) -> u64 {
self.0
}
}
#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct ShortChannelIdDir {
pub short_channel_id: ShortChannelId,
pub direction: u32,
}
impl Serialize for ShortChannelIdDir {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
serializer.serialize_str(&self.to_string())
}
}
impl<'de> Deserialize<'de> for ShortChannelIdDir {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: Deserializer<'de>,
{
use serde::de::Error;
let s: String = Deserialize::deserialize(deserializer)?;
Ok(Self::from_str(&s).map_err(|e| Error::custom(e.to_string()))?)
}
}
impl FromStr for ShortChannelIdDir {
type Err = crate::Error;
fn from_str(s: &str) -> Result<Self, Self::Err> {
let parts: Result<Vec<String>, _> = s.split('/').map(|p| p.parse()).collect();
let parts = parts.with_context(|| format!("Malformed short_channel_id_dir: {}", s))?;
if parts.len() != 2 {
return Err(anyhow!(
"Malformed short_channel_id_dir: element count mismatch"
));
}
Ok(ShortChannelIdDir {
short_channel_id: ShortChannelId::from_str(&parts[0])?,
direction: parts[1].parse::<u32>()?,
})
}
}
impl Display for ShortChannelIdDir {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
write!(
f,
"{}x{}x{}/{}",
self.short_channel_id.block(),
self.short_channel_id.txindex(),
self.short_channel_id.outnum(),
self.direction
)
}
}
#[derive(Clone, Copy, Debug)]
@ -290,7 +407,7 @@ impl<'de> Deserialize<'de> for Outpoint {
}
}
#[derive(Copy, Clone, Serialize, Deserialize, Debug, PartialEq)]
#[derive(Copy, Clone, Serialize, Deserialize, Debug, PartialEq, Eq)]
#[serde(rename_all = "lowercase")]
pub enum ChannelSide {
LOCAL,
@ -328,6 +445,8 @@ impl TryFrom<i32> for ChannelState {
9 => Ok(ChannelState::DUALOPEND_OPEN_INIT),
10 => Ok(ChannelState::DUALOPEND_AWAITING_LOCKIN),
11 => Ok(ChannelState::CHANNELD_AWAITING_SPLICE),
12 => Ok(ChannelState::DUALOPEND_OPEN_COMMITTED),
13 => Ok(ChannelState::DUALOPEND_OPEN_COMMIT_READY),
_ => Err(anyhow!("Invalid channel state {}", value)),
}
}
@ -341,6 +460,7 @@ impl From<i32> for ChannelTypeName {
2 => ChannelTypeName::ANCHORS_ZERO_FEE_HTLC_TX_EVEN,
3 => ChannelTypeName::SCID_ALIAS_EVEN,
4 => ChannelTypeName::ZEROCONF_EVEN,
5 => ChannelTypeName::ANCHORS_EVEN,
o => panic!("Unmapped ChannelTypeName {}", o),
}
}
@ -354,6 +474,7 @@ impl From<ChannelTypeName> for i32 {
ChannelTypeName::ANCHORS_ZERO_FEE_HTLC_TX_EVEN => 2,
ChannelTypeName::SCID_ALIAS_EVEN => 3,
ChannelTypeName::ZEROCONF_EVEN => 4,
ChannelTypeName::ANCHORS_EVEN => 5,
}
}
}
@ -730,7 +851,7 @@ mod test {
});
let p: FundchannelResponse = serde_json::from_value(r).unwrap();
assert_eq!(p.channel_type.unwrap().bits, Some(vec![1,3,5]));
assert_eq!(p.channel_type.unwrap().bits, vec![1, 3, 5]);
}
}
@ -818,20 +939,91 @@ impl Serialize for RoutehintList {
}
impl<'de> Deserialize<'de> for RoutehintList {
fn deserialize<D>(_deserializer: D) -> Result<Self, D::Error>
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: Deserializer<'de>,
{
todo!("Required once we roundtrip, but not necessary for cln-rpc itself")
let hints: Vec<Routehint> = Vec::deserialize(deserializer)?;
Ok(RoutehintList { hints })
}
}
impl<'de> Deserialize<'de> for Routehint {
fn deserialize<D>(_deserializer: D) -> Result<Self, D::Error>
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: Deserializer<'de>,
{
todo!("Required once we roundtrip, but not necessary for cln-rpc itself")
let hops: Vec<Routehop> = Vec::deserialize(deserializer)?;
Ok(Routehint { hops })
}
}
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct DecodeRoutehop {
pub pubkey: PublicKey,
pub short_channel_id: ShortChannelId,
pub fee_base_msat: Amount,
pub fee_proportional_millionths: u32,
pub cltv_expiry_delta: u16,
}
#[derive(Clone, Debug)]
pub struct DecodeRoutehint {
pub hops: Vec<DecodeRoutehop>,
}
#[derive(Clone, Debug)]
pub struct DecodeRoutehintList {
pub hints: Vec<DecodeRoutehint>,
}
impl Serialize for DecodeRoutehint {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
let mut seq = serializer.serialize_seq(Some(self.hops.len()))?;
for e in self.hops.iter() {
seq.serialize_element(e)?;
}
seq.end()
}
}
impl Serialize for DecodeRoutehintList {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
let mut seq = serializer.serialize_seq(Some(self.hints.len()))?;
for e in self.hints.iter() {
seq.serialize_element(e)?;
}
seq.end()
}
}
impl<'de> Deserialize<'de> for DecodeRoutehintList {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: Deserializer<'de>,
{
let hints: Vec<DecodeRoutehint> = Vec::deserialize(deserializer)?;
Ok(DecodeRoutehintList { hints })
}
}
impl<'de> Deserialize<'de> for DecodeRoutehint {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: Deserializer<'de>,
{
let hops: Vec<DecodeRoutehop> = Vec::deserialize(deserializer)?;
Ok(DecodeRoutehint { hops })
}
}

View File

@ -57,9 +57,7 @@ CLOSINGD_COMMON_OBJS := \
common/utxo.o \
common/version.o \
common/wire_error.o \
common/wireaddr.o \
gossipd/gossip_store_wiregen.o \
gossipd/gossipd_peerd_wiregen.o
common/wireaddr.o
lightningd/lightning_closingd: $(CLOSINGD_OBJS) $(CLOSINGD_COMMON_OBJS) $(WIRE_OBJS) $(BITCOIN_OBJS) $(HSMD_CLIENT_OBJS)

View File

@ -20,7 +20,6 @@
#include <common/version.h>
#include <common/wire_error.h>
#include <errno.h>
#include <gossipd/gossipd_peerd_wiregen.h>
#include <hsmd/hsmd_wiregen.h>
#include <inttypes.h>
#include <stdio.h>
@ -128,7 +127,7 @@ static u8 *closing_read_peer_msg(const tal_t *ctx,
static void send_offer(struct per_peer_state *pps,
const struct chainparams *chainparams,
const struct channel_id *channel_id,
const struct pubkey funding_pubkey[NUM_SIDES],
const struct pubkey *funding_pubkey,
const u8 *funding_wscript,
u32 *local_wallet_index,
const struct ext_key *local_wallet_ext_key,
@ -166,7 +165,7 @@ static void send_offer(struct per_peer_state *pps,
/* BOLT #3:
*
* ## Closing Transaction
* ## Legacy Closing Transaction
*...
* Each node offering a signature... MAY eliminate its
* own output.
@ -227,7 +226,7 @@ static struct amount_sat
receive_offer(struct per_peer_state *pps,
const struct chainparams *chainparams,
const struct channel_id *channel_id,
const struct pubkey funding_pubkey[NUM_SIDES],
const struct pubkey *funding_pubkey,
const u8 *funding_wscript,
u32 *local_wallet_index,
const struct ext_key *local_wallet_ext_key,
@ -268,8 +267,8 @@ receive_offer(struct per_peer_state *pps,
*/
else if (fromwire_peektype(msg) == WIRE_SHUTDOWN)
msg = tal_free(msg);
/* channeld may have sent ping: ignore pong! */
else if (fromwire_peektype(msg) == WIRE_PONG)
/* We can get announcement signatures: too late! */
else if (fromwire_peektype(msg) == WIRE_ANNOUNCEMENT_SIGNATURES)
msg = tal_free(msg);
} while (!msg);

View File

@ -16,6 +16,7 @@ COMMON_SRC_NOGEN := \
common/bolt11.c \
common/bolt11_json.c \
common/bolt12.c \
common/bolt12_id.c \
common/bolt12_merkle.c \
common/channel_config.c \
common/channel_id.c \
@ -52,9 +53,10 @@ COMMON_SRC_NOGEN := \
common/interactivetx.c \
common/initial_channel.c \
common/initial_commit_tx.c \
common/invoice_path_id.c \
common/iso4217.c \
common/json_blinded_path.c \
common/json_channel_type.c \
common/json_command.c \
common/json_filter.c \
common/json_param.c \
common/json_parse.c \
@ -69,6 +71,7 @@ COMMON_SRC_NOGEN := \
common/onion_decode.c \
common/onion_encode.c \
common/onionreply.c \
common/onion_message.c \
common/onion_message_parse.c \
common/peer_billboard.c \
common/peer_failed.c \
@ -77,6 +80,7 @@ COMMON_SRC_NOGEN := \
common/per_peer_state.c \
common/permute_tx.c \
common/ping.c \
common/plugin.c \
common/psbt_internal.c \
common/psbt_keypath.c \
common/psbt_open.c \
@ -84,9 +88,11 @@ COMMON_SRC_NOGEN := \
common/random_select.c \
common/read_peer_msg.c \
common/route.c \
common/sciddir_or_pubkey.c \
common/setup.c \
common/shutdown_scriptpubkey.c \
common/sphinx.c \
common/splice_script.c \
common/status.c \
common/status_levels.c \
common/status_wire.c \
@ -112,7 +118,6 @@ COMMON_HEADERS_NOGEN := $(COMMON_SRC_NOGEN:.c=.h) \
common/gossip_constants.h \
common/hsm_version.h \
common/htlc.h \
common/json_command.h \
common/jsonrpc_errors.h \
common/overflows.h

View File

@ -36,3 +36,79 @@ char *encode_scriptpubkey_to_addr(const tal_t *ctx,
return out;
}
static const char *segwit_addr_net_decode(int *witness_version,
uint8_t *witness_program,
size_t *witness_program_len,
const char *addrz,
const struct chainparams *chainparams)
{
if (segwit_addr_decode(witness_version, witness_program,
witness_program_len, chainparams->onchain_hrp,
addrz))
return chainparams->onchain_hrp;
else
return NULL;
}
bool decode_scriptpubkey_from_addr(const tal_t *ctx,
const struct chainparams *chainparams,
const char *address,
u8 **scriptpubkey)
{
struct bitcoin_address destination;
int witness_version;
/* segwit_addr_net_decode requires a buffer of size 40, and will
* not write to the buffer if the address is too long, so a buffer
* of fixed size 40 will not overflow. */
uint8_t witness_program[40];
size_t witness_program_len;
const char *bech32;
u8 addr_version;
if (ripemd160_from_base58(&addr_version, &destination.addr,
address, strlen(address))) {
if (addr_version == chainparams->p2pkh_version) {
*scriptpubkey = scriptpubkey_p2pkh(ctx, &destination);
return true;
} else if (addr_version == chainparams->p2sh_version) {
*scriptpubkey =
scriptpubkey_p2sh_hash(ctx, &destination.addr);
return true;
} else {
return false;
}
/* Insert other parsers that accept pointer+len here. */
return false;
}
bech32 = segwit_addr_net_decode(&witness_version, witness_program,
&witness_program_len, address,
chainparams);
if (bech32) {
bool witness_ok;
if (witness_version == 0) {
witness_ok = (witness_program_len == 20 ||
witness_program_len == 32);
} else if (witness_version == 1) {
witness_ok = (witness_program_len == 32);
} else {
witness_ok = true;
}
if (!witness_ok)
return false;
if (!streq(bech32, chainparams->onchain_hrp))
return false;
*scriptpubkey = scriptpubkey_witness_raw(ctx, witness_version,
witness_program,
witness_program_len);
return true;
}
/* Insert other parsers that accept null-terminated string here. */
return false;
}

Some files were not shown because too many files have changed in this diff Show More