Commit Graph

3574 Commits

Author SHA1 Message Date
Rusty Russell
103a49ef51 xpay: support paying a (simple) bolt12 offer directly.
fetchinvoice is still good for detailed diagnostics and handling
recurring invoices and alternate currencies, but this covers the
"throw some sats" case well.

Changelog-Added: JSON-RPC: `xpay` can now pay a simple offer directly, rather than requiring fetchinvoice first.
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2025-08-18 14:57:46 +09:30
Rusty Russell
5345e71727 offers: fix fetchinvoice from using disconnected peers.
We didn't remove them from the graph if they were disconnected, leading to us trying to send an onion message to it:

```
➜  ~ lightning-cli fetchinvoice lno1pg7y7s69g98zq5rp09hh2arnypnx7u3qvf3nzut68pmkcet2xdm8s7ngw5ux2am4wqekwmtkddkkk7nyv45ryefexum82anr8phpp6qrse80qf0aara4slvcjxrvu6j2rp5ftmjy4yntlsmsutpkvkt6878sy4xtpdc0j42xp72an4cl0unvzm7ckx2e6ltlzlgeekh0hhe0mgs2qgpetp66ufc9pwln9gmyv0gk3ndpqvvtynef8adzm3lxv0astkxunjcqx0fsq8kmx5cz574ft45vcweaf3tffp90fjdfl9gkdh4s6xfxaz7srtmsju9gnr3xerjhjqw4xtsmp55f4jjsxxrch703kx020l6wn2ttcd24w5h8f2lz723lk2kpa8ftkernz7h2qqkd3zecz2jmhucwh555xf0np4w45zm8tlka4ktw6d3ne4l9u678y37d24xjcy3el53faulcu5tzzquxrxvcyrvzgk7tyjeapt8wu858m2msgdznhqxl8fps04lef9dc9c 1sat 
{
   "code": -1,
   "message": "onion msg: unknown next peer 024b9a1fa8e006f1e3937f65f66c408e6da8e1ca728ea43222a7381df1cc449605"
}
```

Fixes: https://github.com/ElementsProject/lightning/issues/8225
Changelog-Fixed: JSON-RPC: `fetchinvoice` is now more reliable.
2025-08-18 14:19:27 +09:30
Rusty Russell
b76d9b3d62 pytest: test for fetchinvoice when a onion-message-capable peer is disconnected.
```
FAILED tests/test_pay.py::test_fetchinvoice_autoconnect_if_disconnected - pyln.client.lightning.RpcError: RPC call failed: method: fetchinvoice, payload: {'offer': 'lno1qgsqvgnwgcg35z6ee2h3yczraddm72xrfua9uve2rlrm9deu7xyfzrcgqypq5tn5v4ehghmxv46xx6rfdemx76trv40kzat5da3k7mnwv43hghmfve0kg6tnvdhkumn9vd6x2ep3zcssxhftzxfdlwsnfcgw2sy8t5mxa0ytcdfat2nkdwqvpy9nnsa9mzza'}, error: {'code': -1, 'message': 'onion msg: unknown next peer 022d223620a359a47ff7f7ac447c85c46c923da53389221a0054c11c1e3ca31d59'}
```

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2025-08-18 14:19:27 +09:30
Rusty Russell
e43a4a96e7 pyln-testing: check plugin notifications against any extant notification schemas.
Note that we need a workaround for deprecated APIs where "channel_state_changed" output "null" which violated the schema.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2025-08-18 10:01:07 +09:30
Rusty Russell
5d5741e681 libplugin: correctly wrap notifications we send in the notification name.
All the core notifications changed over to wrapping the notification
fields in an object with the name of the notification, but notifications
from plugins were missed.

Changelog-Added: Plugins: `channel_hint_update`, `pay_failure` and `pay_success` notifications now have objects of the same name containing the expected fields.
Changelog-Deprecated: Plugins: `channel_hint_update`, `pay_failure` and `pay_success` notification fields outside the same-named object.
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2025-08-18 10:01:07 +09:30
Rusty Russell
16819f345d lightningd: make notifications from plugins just like native ones.
Rather than forcing them to wrap their parameters in a "payload"
sub-object, copy in params directly.  We include the "origin" field
one level up, if they care.

The next patch restores compatibility for the one place we currently use
them, which is the pay plugin.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
Changelog-Deprecated: pyln-client: plugin custom notifications origins and payload (use parameters directly)
2025-08-18 10:01:07 +09:30
Rusty Russell
fc5edea999 pyln-client: adapt for modern plugin notifications.
For older lightningd, we copy field into the raw dict, for newer we recreate the old
"payload" member.

We do fix up the custom_notification test which set params to a string instead of a dict:
that's just weird!

We also change the hacky parsing to proper dict extraction.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
Changelog-Changed: pyln-client: plugin notifications parameters now exposed directly, not wrapped in `params` object.
2025-08-18 10:01:07 +09:30
Rusty Russell
a686bda4cb lightningd: deprecate null short_channel_id and unknown old_state in channel_state_changed notification
We always prefer to omit fields rather than use 'null' (or unknown!).

Note that before this, the schema was broken, so we have to put a special
exemption in for that case.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2025-08-18 10:01:07 +09:30
Rusty Russell
3015bfcf4b pytest: simple test for pay's custom notifications.
Particularly important since we're going to update the format: this makes sure we don't break them!

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2025-08-18 10:01:07 +09:30
ShahanaFarooqui
4b64b694b3 docs: Added fetchbip353 example in autogenerate script
Other doc examples fixes from 25.05 till 25.09 updates.
2025-08-17 09:47:19 +09:30
Rusty Russell
79b959b751 pytest: fix flake in test_route_by_old_scid
```
2025-08-14T11:45:41.7353946Z         # Now l1 tries to send using old scid: should work
2025-08-14T11:45:41.7354652Z         l1.rpc.sendpay(route, inv['payment_hash'], payment_secret=inv['payment_secret'])
2025-08-14T11:45:41.7355321Z >       l1.rpc.waitsendpay(inv['payment_hash'])
2025-08-14T11:45:41.7355644Z 
2025-08-14T11:45:41.7355791Z tests/test_splicing.py:528: 
...
2025-08-14T11:45:41.7383073Z E           pyln.client.lightning.RpcError: RPC call failed: method: waitsendpay, payload: {'payment_hash': '7b74fa9f6a889a16ebf89b8a9468302100f6ad50a771bbab2a16de58dcb1a9a4'}, error: {'code': 203, 'message': 'failed: WIRE_INCORRECT_OR_UNKNOWN_PAYMENT_DETAILS (reply from remote)', 'data': {'created_index': 1, 'id': 1, 'payment_hash': '7b74fa9f6a889a16ebf89b8a9468302100f6ad50a771bbab2a16de58dcb1a9a4', 'groupid': 1, 'destination': '035d2b1192dfba134e10e540875d366ebc8bc353d5aa766b80c090b39c3a5d885d', 'amount_msat': 10000000, 'amount_sent_msat': 10000101, 'created_at': 1755171392, 'status': 'pending', 'erring_index': 2, 'failcode': 16399, 'failcodename': 'WIRE_INCORRECT_OR_UNKNOWN_PAYMENT_DETAILS', 'erring_node': '035d2b1192dfba134e10e540875d366ebc8bc353d5aa766b80c090b39c3a5d885d', 'erring_channel': '103x2x0', 'erring_direction': 0, 'raw_message': '400f000000000098968000000072'}}
```

Caused by:

```
2025-08-14T11:45:41.9275961Z lightningd-3 2025-08-14T11:36:32.700Z DEBUG   022d223620a359a47ff7f7ac447c85c46c923da53389221a0054c11c1e3ca31d59-chan#1: Expiry cltv too soon 118 < 114 + 5
```

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2025-08-15 17:13:31 +09:30
Rusty Russell
733bdfa67d lightningd: add channel_type to openchannel & openchannel2 hooks.
An obvious omission!

Changelog-Added: Plugins: `openchannel` and `openchannel2` hooks now expose the `channel_type` field for the offered channel.
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2025-08-15 11:11:39 +09:30
Rusty Russell
841a8bd03a lightningd: extract core of coin_movement notification, for use in list functions.
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
Changelog-Deprecated: JSON-RPC: `coin_movement` notification `utxo_txid`, `vout` and `txid` fields (use `utxo` and `spending_txid`).
Changelog-Added: JSON-RPC: `coin_movement` notification `utxo` field.
Changelog-Added: JSON-RPC: `coin_movement` notification `spending_txid` field.
2025-08-14 19:49:09 +09:30
Rusty Russell
650f3882dd lightningd: separate coin_movement tags array into primary_tag and extra_tags.
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
Changelog-Deprecated: JSON-RPC: `coin_movement` notification `tags` array (use `primary_tag` and `extra_tags`).
Changelog-Added: JSON-RPC: `coin_movement` notification `primary_tag` and `extra_tags`.
2025-08-14 19:49:09 +09:30
Rusty Russell
9c6e7b8d42 pytest: don't assume that tags will always be in the same order.
This isn't a robust assumption, so sort them before comparison.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2025-08-14 19:49:09 +09:30
Rusty Russell
aee7ebbeef onchaind: don't consider our anchors to be payments into the wallet.
This makes our final balance not match our wallet:
1. We only spend the anchor when we need to boost the commitment tx,
   which we don't always do (sometimes the peer does, sometimes it's
   not worth it).
2. We don't put the UTXO in our wallet, because we don't consider it
   "ours": anyone can spend it after 16 blocks.

We used to use the tag "ignored" for this, but that's overly complex
IMHO.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2025-08-14 19:49:09 +09:30
Rusty Russell
9b4a7085c2 pytest: save pre-movement dbs, and accounting dbs.
We can use these to test migrations.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2025-08-14 19:49:09 +09:30
Peter Neuroth
dbbb113123 tests: Add tests for extra_tlvs in hook
Adds some testcases for custom tlvs, set by a htlc_accepted_hook. We
check that the custom tlvs replace the update_add_htlc_tlvs and get
forwarded to the peer. We also check that a malformed tlv will result in
a **BROKEN** behaviour.

Signed-off-by: Peter Neuroth <pet.v.ne@gmail.com>
2025-08-14 18:57:05 +09:30
Peter Neuroth
ef52de88aa channeld: Add extra_tlvs to incomming wire msg
This appends the extra_tlvs to the internal channeld_offer_htlc wire
msg. We also recombine the extra_tlvs with the blinded path key for
forwarding htlcs.

Signed-off-by: Peter Neuroth <pet.v.ne@gmail.com>
2025-08-14 18:57:05 +09:30
Peter Neuroth
f4cc633c6f channeld: add extra_tlvs from update_add_htlc msg
We currently only consider known tlv types in the internal
representation of a htlc. This commit adds the remaining unknown tlv
fields to the htlc as well. This is in prepareation to forward these to
the htlc_accepted_hook.

Signed-off-by: Peter Neuroth <pet.v.ne@gmail.com>
2025-08-14 18:57:05 +09:30
daywalker90
e3e41163e2 cln-bip353: add plugin that fetches payment instructions from human readable addresses
Changelog-Add: new plugin cln-bip353 that can fetch BIP-353 payment instructions from human readable addresses
2025-08-14 18:41:23 +09:30
Rusty Russell
c88ec27de3 pytest: test xpay notifications.
The custom_notifications handler produces really ugly results, and I
was lazy, but it works!

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2025-08-14 16:52:44 +09:30
Rusty Russell
f265a956c7 pytest: test persistence of old scids, even if we spliced multiple times.
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2025-08-14 14:04:11 +09:30
Rusty Russell
d70fc13b54 lightningd: consider old scids when looking up channels (for routing).
Changelog-Fixed: Protocol: we now allow routing through old short-channel-ids once a splice is done (previously we would refuse, leading to a 6 block gap in service).
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2025-08-14 14:04:11 +09:30
Rusty Russell
931924a108 pytest: test if we correctly route using old scids after splice
Spoiler: we don't!

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2025-08-14 14:04:11 +09:30
Dusty Daemon
a17b364c6b splice: Test for two channel splice
A python test that splices into two channels at the same time with on transaction.

Changelog-Added: Adding support for cross-channel splicing.
2025-08-14 04:12:17 +09:30
ShahanaFarooqui
bab6429da0 tests: add sql json function tests 2025-08-13 15:52:53 +09:30
Rusty Russell
506fa914e0 lightningd: always tell openingd/dualopend what channel type we want.
Prior to it being compulsory, these daemons would need a default value.  Now it's
always required, it's clearer if it's always told.

There's no "default_channel_type" now everyone has to specify channel_type either,
so rename it to "desired_channel_type" and put it in lightningd specifically.

Note that the channel_type can have options added: either option_scid_alias or option_zeroconf.

This results in a slight behavior change: we will get type zeroconf even if we didn't ask for it, if they gave it to us.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
Changelog-Changed: JSON-RPC: fundchannel / fundchannel_start returned `channel_type` will include option_zeroconf if it was implied by a 0 minimum_depth, even if we didn't explicitly ask for a zero conf channel.
2025-08-13 14:20:28 +09:30
Rusty Russell
a7316fef83 pytest: actually test channel_type when negotiating prviate channel.
Makes sure we don't break it!

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2025-08-13 14:20:28 +09:30
Rusty Russell
193ac6fc77 pytest: test what happens if we *explicitly* ask for a zeroconf channel.
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2025-08-13 14:20:28 +09:30
Rusty Russell
7893c878b1 pytest: use _ not - in plugin options to zeroconf-selective.py.
This allows us to specify:

	l2.rpc.plugin_start(plugin_path, zeroconf_allow=l1.info['id'])

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2025-08-13 14:20:28 +09:30
Rusty Russell
4e94a6cb2b lightningd: make option_channel_type compulsory.
As per BOLT recommendation https://github.com/lightning/bolts/pull/1232, this means
we will insist on this being available.

For CLN, we added this in 0.12.0 (2022-08-23), though there were fixes as late as 24.02. Either way that's well outside our support window.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
Closes: https://github.com/ElementsProject/lightning/issues/8152
Changelog-Changed: Protocol: We now insist that peers support `option_channel_type` (in CLN since 0.12.0 in late 2022, similar for other implementations).
2025-08-13 14:20:28 +09:30
Alex Myers
d427a6644e pytest: test python plugin installation via uv 2025-08-12 09:28:21 +09:30
Alex Myers
542b54c649 pytest: refactor reckless check_stderr 2025-08-12 09:28:21 +09:30
Alex Myers
da737d2228 pytest: add reckless regex search 2025-08-12 09:28:21 +09:30
Lakshya Singh
d428998d5d fix: replace deprecated flask.escape with markupsafe.escape
Updates tests/rkls_github_canned_server.py to use markupsafe.escape 
instead of the deprecated flask.escape function. The flask.escape 
function is now deprecated and will be removed in a future Flask 
release, so this change ensures forward compatibility.
2025-08-11 11:06:22 +09:30
Lakshya Singh
f442bd5012 fix: flake8 lint rules
Remove unnecessary global declarations across multiple test files. 
This change improves code quality by eliminating redundant global 
statements for variables that are already accessible in their 
respective scopes. Add proper type annotation for fees_from_status 
in test_closing.py and import the required typing modules. These 
changes maintain the same functionality while making the code cleaner 
and more compliant with Python best practices.
2025-08-11 11:06:22 +09:30
Lakshya Singh
04afdc478d feat: add pytest config
Add pytest.ini with pythonpath = . configuration to ensure modules 
are properly discovered when running tests. Also add empty 
__init__.py file to make the tests directory a proper Python package.
2025-08-11 11:06:22 +09:30
Lagrang3
767893de7a askrene: rework the caller of the MCF solver
We use a wrapper around the MCF solver that takes care of finding the
best linearization parameters and fixing the flow values to meet the
htlc_min and htlc_max constraints.
We have reworked the current implementation and made it a bit more
similar to renepay's version.

Out of 50000 simulated payment situations distributed accross payment
amounts of 1e2, 1e3, 1e4, 1e5 and 1e6 sats, we find that 133 failed
cases in the master branch turn to success with the current changes,
while only 3 success cases in the master are not solved by the changes.

                master
            +-------+------+
            | S     | F    |
        +---+-------+------+
        | S | 46329 | 133  |
changes +---+-------+------+
        | F | 3     | 3535 |
        +---+-------+------+

Out of the 133 cases that flipped from failure to success the failed
reasons were:

122 -> "Could not find route without excessive cost"
5   -> "We couldn't quite afford it"
5   -> "Amount *msat below minimum"
1   -> tripped an HTLC min check

Changelog-None.

Signed-off-by: Lagrang3 <lagrang3@protonmail.com>
2025-08-08 14:07:51 +09:30
Rusty Russell
6a94683db4 hsmd: don't assert that our own locktime is > 0.
By policy, our stub hsmd accepts everything: openingd is supposed to
sort this out (or use VLS for a real HSM implementation!).

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
Changelog-Fixed: Config: the node no longer crashes if you set `watchtime-blocks` to 0 (which is fine for testing: don't do this on mainnet!).
2025-08-07 14:55:30 +09:30
Rusty Russell
e6b14da968 pytest: test for watchtime-blocks=0
It's not really advisable, but it's legal, though our HSMD refuses to
sign off on operations.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2025-08-07 14:55:30 +09:30
Chandra Pratap
a1c554fd76 fuzz-tests: Add coverage increasing inputs to seed corpora
Improvements in the fuzz-testing scheme of
`fuzz-bolt12-invrequest-decode` led to the discovery of test inputs
that result in greater in code coverage.

Add these inputs to the test's seed corpus.
2025-08-06 13:53:49 +09:30
Chandra Pratap
d9685a6c63 fuzz-tests: Make fuzz-bolt12-invrequest-decode roundrip
Changelog-None: Currently, the `BOLT #12` invrequest parsing test
only tests the invrequest decode function. Add a test for the
encoding function as well by making the test roundtrip.
2025-08-06 13:53:49 +09:30
daywalker90
bf37d41c7e clnrest: add more valid request and response types
Changelog-Added: clnrest can now return successful responses as xml, yaml, or form-encoded in addition to json defined in the 'Accept' header. The same goes for request types defined in the 'Content-type' header.
2025-07-25 08:18:44 -07:00
daywalker90
2e7181d04f wss-proxy: replaced by a rust version
Changelog-Changed: wss-proxy.py was replaced by a rust version with support for multiple `wss-bind-addr`. If you install CLN from pre-compiled binaries you must remove the old wss-proxy directory first before installing CLN, usually
it is located in `/usr/local/libexec/c-lightning/plugins/wss-proxy`. If you compile from source `make` will take care of this automatically.
2025-07-24 12:42:06 -07:00
Lagrang3
420cff9350 askrene: mcf: trade granularity for performance
Speed in getroutes up by setting the granularity to 1000

Amount (sats) | speedup
-----------------------
          100 | 1.00
         1000 | 1.00
        10000 | 1.06
       100000 | 1.31
      1000000 | 2.64

Worst runtime of getroutes

Amount (sats) | before (ms) | after (ms)
--------------------------------------
          100 | 1507        | 761
         1000 | 2129        | 1214
        10000 | 1632        | 1043
       100000 | 2004        | 1150
      1000000 | 27170       | 3289

Changelog-None

Signed-off-by: Lagrang3 <lagrang3@protonmail.com>
2025-07-19 10:09:17 +09:30
Lagrang3
b7f3d7bcc4 askrene: prune un-used arcs
From the multiple arcs that derive from the same channel we consider
only those with the smallest cost such that the payment amount and HTLC
max can fit in their combined capacity, ie. we prune high cost arcs that
surely will never be used by the optimal solution.

This reduces the number of arcs in the graph approximately from 8 arcs
per channel to approximately 2 arcs per channel.

No pruning.
amount:		100 	1000 	10000 	100000 	1000000
channels:	104741	106163	106607	106654	106666
arcs:		837928	849304	852856	853232	853328

Prune, limit the channel capacity by its HTLC max
amount:		100 	1000 	10000 	100000 	1000000
channels:	104741	106163	106607	106654	106666
arcs:		255502	259314	260538	260676	260704

Prune, limit the channel capacity to the payment amount
amount:		100 	1000 	10000 	100000 	1000000
channels:	104741	106163	106607	106654	106666
arcs:		209482	216270	228618	295450	432468

Prune, limit the channel capacity to the payment amount and its HTLC max
amount:		100 	1000 	10000 	100000 	1000000
channels:	104741	106163	106607	106654	106666
arcs:		209480	212324	213242	215726	228018

This produces a slight speedup for MCF computations:

Amount (sats) | speedup
-----------------------
          100 | 1.89
         1000 | 1.77
        10000 | 1.25
       100000 | 1.25
      1000000 | 1.18

Changelog-None

Signed-off-by: Lagrang3 <lagrang3@protonmail.com>
2025-07-19 10:09:17 +09:30
Lagrang3
25c88447fa askrene: add algorithm for single path routing
Changelog-Added: askrene: an optimal single-path solver has been added, it can be called using the developer option --dev_algorithm=single-path or by adding the layer "auto.no_mpp_support"

Signed-off-by: Lagrang3 <lagrang3@protonmail.com>
2025-07-18 15:13:41 +09:30
Rusty Russell
725c417198 pytest: add debug print to diagnose flake in test_peer_anchor_push
Sometimes the feerate is 5 too high.  But without seeing the actual txs it's
looking at, it's hard to know why.

```
actual_feerate = 13005.66942869603, expected_feerate = 13000

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

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2025-07-11 12:24:35 +09:30
Rusty Russell
1b89ea6776 pytest: avoid bad gossip flake in test_htlc_no_force_close
l3 closes with l2 unilaterally, but l2 sends l1 the channel_announce after
that, when it has never seen it before.  The solution is to wait until
l1 has seen the channel before we start the rest of the test:

```
E           ValueError:
E           Node errors:
E            - lightningd-2: had warning messages
E            - lightningd-1: had bad gossip messages
...
lightningd-2 2025-07-09T07:55:59.778Z DEBUG   0266e4598d1d3c415f572a8488830b60f7e744ed9235eb0b1ba93283b315c03518-connectd: peer_in WIRE_WARNING
lightningd-2 2025-07-09T07:55:59.778Z INFO    0266e4598d1d3c415f572a8488830b60f7e744ed9235eb0b1ba93283b315c03518-connectd: Received WIRE_WARNING: WARNING: channel_announcement: no unspent txout 103x1x0
lightningd-1 2025-07-09T07:55:59.781Z DEBUG   022d223620a359a47ff7f7ac447c85c46c923da53389221a0054c11c1e3ca31d59-channeld-chan#1: billboard: Channel ready for use.
lightningd-1 2025-07-09T07:55:59.782Z TRACE   gossipd: channel_announcement: got reply for 103x1x0...
lightningd-1 2025-07-09T07:55:59.782Z TRACE   022d223620a359a47ff7f7ac447c85c46c923da53389221a0054c11c1e3ca31d59-gossipd: Bad gossip order: channel_announcement: no unspent txout 103x1x0
```

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2025-07-11 12:24:35 +09:30