Skip to content

Commit 7712956

Browse files
committed
offers: add used_count to listoffers
This adds a new 'used_count' field to the 'listoffers' RPC command output to see the exact number of times a BOLT12 offer has been paid by counting associated settled invoices. Changelog-Added: add a new 'used_count' field to the 'listoffers' RPC command Closes #9146
1 parent 11b8324 commit 7712956

13 files changed

Lines changed: 1026 additions & 342 deletions

File tree

.msggen.json

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3181,7 +3181,8 @@
31813181
"ListOffers.offers[].label": 6,
31823182
"ListOffers.offers[].offer_id": 1,
31833183
"ListOffers.offers[].single_use": 3,
3184-
"ListOffers.offers[].used": 5
3184+
"ListOffers.offers[].used": 5,
3185+
"ListOffers.offers[].used_count": 9
31853186
},
31863187
"ListoffersRequest": {
31873188
"ListOffers.active_only": 2,
@@ -11483,6 +11484,10 @@
1148311484
"added": "pre-v0.10.1",
1148411485
"deprecated": null
1148511486
},
11487+
"ListOffers.offers[].used_count": {
11488+
"added": "v26.09",
11489+
"deprecated": null
11490+
},
1148611491
"ListPays": {
1148711492
"added": "pre-v0.10.1",
1148811493
"deprecated": null

cln-grpc/proto/node.proto

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

cln-grpc/src/convert.rs

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

cln-rpc/src/model.rs

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

contrib/msggen/msggen/schema.json

Lines changed: 37 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -24414,7 +24414,8 @@
2441424414
"single_use",
2441524415
"force_paths",
2441624416
"bolt12",
24417-
"used"
24417+
"used",
24418+
"used_count"
2441824419
],
2441924420
"properties": {
2442024421
"offer_id": {
@@ -24461,6 +24462,12 @@
2446124462
"True if an associated invoice has been paid."
2446224463
]
2446324464
},
24465+
"used_count": {
24466+
"type": "u64",
24467+
"description": [
24468+
"The number of times this offer has been paid."
24469+
]
24470+
},
2446424471
"label": {
2446524472
"type": "string",
2446624473
"description": [
@@ -24498,24 +24505,27 @@
2449824505
"active": true,
2449924506
"single_use": false,
2450024507
"bolt12": "lno1qgsq000bolt210002100021000210002100021000210002100021000210002100021000210002100021000210002100021000210002100021000210002100021000",
24508+
"used": false,
2450124509
"description": "Fish sale!",
24502-
"used": false
24510+
"used_count": 0
2450324511
},
2450424512
{
2450524513
"offer_id": "offeridl22000002200000220000022000002200000220000022000002200000",
2450624514
"active": true,
2450724515
"single_use": false,
2450824516
"bolt12": "lno1qgsq000bolt220002200022000220002200022000220002200022000220002200022000220002200022000220002200022000220002200022000220002200022000",
24517+
"used": false,
2450924518
"description": "Coffee",
24510-
"used": false
24519+
"used_count": 0
2451124520
},
2451224521
{
2451324522
"offer_id": "offeridl23000002300000230000023000002300000230000023000002300000",
2451424523
"active": true,
2451524524
"single_use": false,
2451624525
"bolt12": "lno1qgsq000bolt230002300023000230002300023000230002300023000230002300023000230002300023000230002300023000230002300023000230002300023000",
24526+
"used": false,
2451724527
"description": "Movie ticket",
24518-
"used": false
24528+
"used_count": 0
2451924529
}
2452024530
]
2452124531
}
@@ -24535,7 +24545,29 @@
2453524545
"active": true,
2453624546
"single_use": false,
2453724547
"bolt12": "lno1qgsq000bolt230002300023000230002300023000230002300023000230002300023000230002300023000230002300023000230002300023000230002300023000",
24538-
"used": false
24548+
"used": false,
24549+
"used_count": 0
24550+
}
24551+
]
24552+
}
24553+
},
24554+
{
24555+
"request": {
24556+
"id": "example:listoffers#3",
24557+
"method": "listoffers",
24558+
"params": [
24559+
"offeridl23000002300000230000023000002300000230000023000002300000"
24560+
]
24561+
},
24562+
"response": {
24563+
"offers": [
24564+
{
24565+
"offer_id": "offeridl23000002300000230000023000002300000230000023000002300000",
24566+
"active": true,
24567+
"single_use": false,
24568+
"bolt12": "lno1qgsq000bolt230002300023000230002300023000230002300023000230002300023000230002300023000230002300023000230002300023000230002300023000",
24569+
"used": true,
24570+
"used_count": 1
2453924571
}
2454024572
]
2454124573
}

contrib/pyln-grpc-proto/pyln/grpc/node_pb2.py

Lines changed: 331 additions & 331 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

contrib/pyln-testing/pyln/testing/grpc2py.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1698,6 +1698,7 @@ def listoffers_offers2py(m):
16981698
"offer_id": hexlify(m.offer_id), # PrimitiveField in generate_composite
16991699
"single_use": m.single_use, # PrimitiveField in generate_composite
17001700
"used": m.used, # PrimitiveField in generate_composite
1701+
"used_count": m.used_count, # PrimitiveField in generate_composite
17011702
})
17021703

17031704

doc/schemas/listoffers.json

Lines changed: 37 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,8 @@
4444
"single_use",
4545
"force_paths",
4646
"bolt12",
47-
"used"
47+
"used",
48+
"used_count"
4849
],
4950
"properties": {
5051
"offer_id": {
@@ -91,6 +92,12 @@
9192
"True if an associated invoice has been paid."
9293
]
9394
},
95+
"used_count": {
96+
"type": "u64",
97+
"description": [
98+
"The number of times this offer has been paid."
99+
]
100+
},
94101
"label": {
95102
"type": "string",
96103
"description": [
@@ -128,24 +135,27 @@
128135
"active": true,
129136
"single_use": false,
130137
"bolt12": "lno1qgsq000bolt210002100021000210002100021000210002100021000210002100021000210002100021000210002100021000210002100021000210002100021000",
138+
"used": false,
131139
"description": "Fish sale!",
132-
"used": false
140+
"used_count": 0
133141
},
134142
{
135143
"offer_id": "offeridl22000002200000220000022000002200000220000022000002200000",
136144
"active": true,
137145
"single_use": false,
138146
"bolt12": "lno1qgsq000bolt220002200022000220002200022000220002200022000220002200022000220002200022000220002200022000220002200022000220002200022000",
147+
"used": false,
139148
"description": "Coffee",
140-
"used": false
149+
"used_count": 0
141150
},
142151
{
143152
"offer_id": "offeridl23000002300000230000023000002300000230000023000002300000",
144153
"active": true,
145154
"single_use": false,
146155
"bolt12": "lno1qgsq000bolt230002300023000230002300023000230002300023000230002300023000230002300023000230002300023000230002300023000230002300023000",
156+
"used": false,
147157
"description": "Movie ticket",
148-
"used": false
158+
"used_count": 0
149159
}
150160
]
151161
}
@@ -165,7 +175,29 @@
165175
"active": true,
166176
"single_use": false,
167177
"bolt12": "lno1qgsq000bolt230002300023000230002300023000230002300023000230002300023000230002300023000230002300023000230002300023000230002300023000",
168-
"used": false
178+
"used": false,
179+
"used_count": 0
180+
}
181+
]
182+
}
183+
},
184+
{
185+
"request": {
186+
"id": "example:listoffers#3",
187+
"method": "listoffers",
188+
"params": [
189+
"offeridl23000002300000230000023000002300000230000023000002300000"
190+
]
191+
},
192+
"response": {
193+
"offers": [
194+
{
195+
"offer_id": "offeridl23000002300000230000023000002300000230000023000002300000",
196+
"active": true,
197+
"single_use": false,
198+
"bolt12": "lno1qgsq000bolt230002300023000230002300023000230002300023000230002300023000230002300023000230002300023000230002300023000230002300023000",
199+
"used": true,
200+
"used_count": 1
169201
}
170202
]
171203
}

lightningd/offer.c

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
#include <common/bolt12_id.h>
55
#include <common/bolt12_merkle.h>
66
#include <common/json_command.h>
7+
#include <common/utils.h>
78
#include <hsmd/hsmd_wiregen.h>
89
#include <inttypes.h>
910
#include <lightningd/hsm_control.h>
@@ -148,6 +149,23 @@ static const struct json_command createoffer_command = {
148149
};
149150
AUTODATA(json_command, &createoffer_command);
150151

152+
/* Helper for fast in-memory lookup of an offer's successful payment count */
153+
static u64 offer_payment_count_find(const struct offer_payment_count *counts,
154+
const struct sha256 *id)
155+
{
156+
struct offer_payment_count key;
157+
const struct offer_payment_count *match;
158+
159+
if (!counts || tal_count(counts) == 0)
160+
return 0;
161+
162+
key.offer_id = *id;
163+
match = bsearch(&key, counts, tal_count(counts), sizeof(*counts),
164+
(int (*)(const void *, const void *))offer_payment_count_cmp);
165+
166+
return match ? match->count : 0;
167+
}
168+
151169
static struct command_result *json_listoffers(struct command *cmd,
152170
const char *buffer,
153171
const jsmntok_t *obj UNNEEDED,
@@ -182,11 +200,14 @@ static struct command_result *json_listoffers(struct command *cmd,
182200
description = offer_description_from_b12(tmpctx, cmd->ld, b12);
183201
if (description)
184202
json_add_stringn(response, "description", description, tal_bytelen(description));
203+
u64 used_count = wallet_offer_count_payments(wallet, offer_id);
204+
json_add_u64(response, "used_count", used_count);
185205
json_object_end(response);
186206
}
187207
} else {
188208
struct db_stmt *stmt;
189209
struct sha256 id;
210+
struct offer_payment_count *counts = wallet_offer_all_payment_counts(wallet, tmpctx);
190211

191212
for (stmt = wallet_offer_id_first(cmd->ld->wallet, &id);
192213
stmt;
@@ -201,6 +222,8 @@ static struct command_result *json_listoffers(struct command *cmd,
201222
description = offer_description_from_b12(tmpctx, cmd->ld, b12);
202223
if (description)
203224
json_add_stringn(response, "description", description, tal_bytelen(description));
225+
u64 used_count = offer_payment_count_find(counts, &id);
226+
json_add_u64(response, "used_count", used_count);
204227
json_object_end(response);
205228
}
206229
}

0 commit comments

Comments
 (0)