Commit graph

103 commits

Author SHA1 Message Date
Rusty Russell
a6cf4915e5 offers: limit expiry to offer limit, or 10 minutes with currency conversion.
This mirrors the previous commit, where we did it for recurring offers.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
Changelog-Fixed: Offers: we set a 10 minute expiry when we create invoices for offers in other currencies.
2026-08-04 18:51:43 -03:00
Rusty Russell
446312cf1b offers: limit invoices to 10 minutes for recurring offers in other currencies.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2026-08-04 18:51:43 -03:00
Rusty Russell
1189175cbc common/bolt12: use a const char * for fail reason.
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2026-05-11 11:13:55 +09:30
Rusty Russell
de23003f80 Update outdated BOLT quotes in HTLC/closing handling.
Mose of these are from the stricter `...` which won't cross section
boundaries.  The listoffers_done doesn't actually need the ellipsis at
all.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2026-04-30 12:17:43 +09:30
Rusty Russell
abd9cd779b offers: use amount hints in find_best_peer for blinded paths.
This lets us reliably eliminate peers which can't give us anything
when seeking blinded paths for invoices.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2026-04-02 10:36:10 +10:30
Rusty Russell
d70b227ffc offers: when creating an invoice for an offer, only reuse fronting paths.
Now we know whether blinded paths in the offer were added explicitly
(by the fronting_nodes option to the `offer command, or via the
`payment-fronting-node` config option) we know whether we need to use
them when minting an invoice.

Previously when I introduced fronting nodes in this release, we
*always* reused them.  But that's not quite right: the blinded path
for the offer can use any peer, but for the invoice we need to use
a peer with sufficient capacity to pay us.  For some offers we won't
even know the amount at the time the offer is made.

So now we only force reuse of the offer's paths when they were set by
the user in the first place: otherwise, we can be more flexible in
path selection when minting the invoice.  This is consistent with what
we did before introducing fronting.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2026-04-02 10:36:10 +10:30
Rusty Russell
9fa7c937ea offers: only use blinded path nodes from offers when creating invoice for invoice_request.
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2026-02-23 19:05:37 +10:30
Rusty Russell
64e4519288 offers: allow explicit fronting nodes for an offer.
The next commit makes us honor these when issuing a payment.

Changelog-Added: JSON-RPC: `offer` now has a `fronting_nodes` option to specify neighbors for payer to use to fetch invoices and make payments.
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2026-02-23 19:05:37 +10:30
Rusty Russell
ae21089a77 offers: honor payment-fronting-nodes when creating invoices.
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2026-02-23 19:05:37 +10:30
Rusty Russell
25e2374f76 offers: modify find_best_peer() to only select from fronting nodes if set.
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2026-02-23 19:05:37 +10:30
Rusty Russell
9eee744df3 lightningd: honor payment-fronting-node when making bolt12 offers.
We use all the fronting nodes when creating offers.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2026-02-23 19:05:37 +10:30
Rusty Russell
572d4db8fc offers: encapsulate globals in plugin_get_data()
This is how modern plugins do it, and it has the benefit of not
requiring extra code for memleak tracking.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2026-02-23 19:05:37 +10:30
21M4TW
29e4c3fef2 offers: require opt_onion_message for incoming invoices too.
Changelog-Fixed: offers: require peers for blinded paths to have `option_onion_messages`, due to reports of LND not forwarding our blinded payments correctly.
2025-11-18 14:31:04 +10:30
Rusty Russell
a3441ff2d0 offers: make find_best_peer take a feature bitmap.
This means we can ask for more than one required feature at a time.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2025-11-18 14:31:04 +10:30
Rusty Russell
8b9020d7b9 global: use clock_time in place of time_now().
Except for tracing, that sticks with time_now().

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2025-11-13 21:21:29 +10:30
Rusty Russell
f8fd97fb5d global: replace randombytes_buf() with randbytes() wrapper.
This allows us to override it for deterministic results.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2025-11-13 21:21:29 +10:30
Rusty Russell
6e5cb299dd global: remove unnecessary includes from C files.
Basically, `devtools/reduce-includes.sh */*.c`.

Build time from make clean (RUST=0) (includes building external libs):

Before:
	real    0m38.944000-40.416000(40.1131+/-0.4)s
	user    3m6.790000-17.159000(15.0571+/-2.8)s
	sys     0m35.304000-37.336000(36.8942+/-0.57)s
After:
	real    0m37.872000-39.974000(39.5466+/-0.59)s
	user    3m1.211000-14.968000(12.4556+/-3.9)s
	sys     0m35.008000-36.830000(36.4143+/-0.5)s

Build time after touch config.vars (RUST=0):

Before:
	real    0m19.831000-21.862000(21.5528+/-0.58)s
	user    2m15.361000-30.731000(28.4798+/-4.4)s
	sys     0m21.056000-22.339000(22.0346+/-0.35)s

After:
	real    0m18.384000-21.307000(20.8605+/-0.92)s
	user    2m5.585000-26.843000(23.6017+/-6.7)s
	sys     0m19.650000-22.003000(21.4943+/-0.69)s

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2025-10-23 06:44:04 +10:30
Rusty Russell
f6a4e79420 global: remove unnecessary includes from headers.
Each header should only include the other headers it needs to compile;
`devtools/reduce-includes.sh */*.h` does this.  The C files then need
additional includes if they don't compile.

And remove the entirely useless wire/onion_wire.h, which only serves to include wire/onion_wiregen.h.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2025-10-23 06:44:04 +10:30
Rusty Russell
512f328730 wire: update to slight spec neating.
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2025-10-01 15:31:30 +09:30
Rusty Russell
5e53af7d3f plugins/offers: handle invoice_request with invreq_recurrence_cancel
In this case, we make an immediately-expiring invoice.  This correctly blocks
any successive requests for invoices, as per the spec requirement.

This means we have to handle invoice_requests without reply_path, amounts
or quantity *if* they specify invreq_recurrence_cancel.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2025-10-01 15:31:30 +09:30
Rusty Russell
b30e063432 plugins/fetchinvoice: allow use of expired offers *for recurrence*.
We added this to the recurrence spec: the offer expiration only applies to the
first request, not subsequent ones.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2025-10-01 15:31:30 +09:30
Rusty Russell
559e3fc447 common: fix bolt12 quotes to bring them up-to-date.
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2025-10-01 15:31:30 +09:30
Rusty Russell
54444e4337 BOLT12: Update recurrence to latest spec draft.
Changes:
* Fields renumbered to their draft values + billion.
* offer_recurrence now comes in compulsory or optional (backwards compat) flavors.
* `proportional_amount` is now inside `offer_recurrence_base` not `offer_recurrence_paywindow`.
* New field `invreq_recurrence_cancel`.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
Changelog-EXPERIMENTAL: Draft specification for recurring offers changed: old recurring offers will no longer work.
2025-10-01 15:31:30 +09:30
Rusty Russell
e7ea57e130 BOLT12: Remove start_any_period from recurrence_base.
Offer_absolute_expiry should be used if you want to require starting at the start.

Changelog-EXPERIMENTAL: Protocol: BOLT 12 recurrence `start_any_period` removed, use expiry if you need to restrict when they can start using the offer.
2025-10-01 15:31:30 +09:30
Rusty Russell
afa7aead24 offers: loosen payment_constraints on invoices' blinded paths.
In practice, we were too strict.  Here's Phoenix paying my node via another node:

```
2025-08-25T13:57:53.311Z DEBUG   02...-chan#216: Failing HTLC because of an invalid payload (TLV 10 pos 103): cltv_expiry 911816 > payment_constraint 911721
```

We add 6 blocks, but this is supposed to be the *max* allowed.  Increase it to 1008, to allow shadow padding.  Here are the CLTV delays across advertized channels in the network: most are far less than this:

Count   Delay
      1 0
      1 4
      3 12
    899 18
    602 20
      1 22
      3 24
      1 25
      9 26
      5 29
     72 30
     54 32
   4352 34
      2 35
      6 36
     10 37
     27 38
      8 39
  15256 40
     94 42
    102 44
     13 45
     20 46
     87 48
    230 50
    100 51
     14 55
    316 60
     29 64
     30 65
     24 68
     82 69
      9 70
    779 72
     13 77
    243 78
      1 79
  26793 80
      1 82
      6 83
      1 84
     18 85
      1 86
      9 87
     16 88
    101 89
      2 90
     11 96
    113 99
   9527 100
     41 112
     34 118
    132 119
    403 120
     24 128
    232 140
    138 142
  14303 144
      2 145
     41 150
      6 160
      3 172
      8 174
     27 180
      4 190
    297 200
     99 210
     34 216
    219 222
     15 240
    105 288
     17 300
      7 336
      1 360
     19 400
     24 420
     26 432
     20 450
      1 480
     12 500
      1 720
      1 850
      1 1000
      1 1002
      1 1144
      1 1192
      5 1201
      1 1444
      1 1795
      1 1900
      1 2016

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
Changelog-Changed: Protocol: Offers on nodes with only private channels are now payable (i.e. no more blinded path errors!).
Fixes: https://github.com/ElementsProject/lightning/issues/7718
2025-08-27 12:09:20 +09: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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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