Skip to content

Commit 0610f66

Browse files
rustyrussellcdecker
authored andcommitted
bolt11: handle r value fee spec change.
We don't use it yet, but now we'll decode correctly. See: lightning/bolts#317 lightning-rfc commit: ef053c0 Signed-off-by: Rusty Russell <[email protected]>
1 parent e9f9721 commit 0610f66

File tree

7 files changed

+36
-26
lines changed

7 files changed

+36
-26
lines changed

common/bolt11.c

+6-3
Original file line numberDiff line numberDiff line change
@@ -378,7 +378,8 @@ static bool fromwire_route_info(const u8 **cursor, size_t *max,
378378
{
379379
fromwire_pubkey(cursor, max, &route_info->pubkey);
380380
fromwire_short_channel_id(cursor, max, &route_info->short_channel_id);
381-
route_info->fee = fromwire_u64(cursor, max);
381+
route_info->fee_base_msat = fromwire_u32(cursor, max);
382+
route_info->fee_proportional_millionths = fromwire_u32(cursor, max);
382383
route_info->cltv_expiry_delta = fromwire_u16(cursor, max);
383384
return *cursor != NULL;
384385
}
@@ -387,7 +388,8 @@ static void towire_route_info(u8 **pptr, const struct route_info *route_info)
387388
{
388389
towire_pubkey(pptr, &route_info->pubkey);
389390
towire_short_channel_id(pptr, &route_info->short_channel_id);
390-
towire_u64(pptr, route_info->fee);
391+
towire_u32(pptr, route_info->fee_base_msat);
392+
towire_u32(pptr, route_info->fee_proportional_millionths);
391393
towire_u16(pptr, route_info->cltv_expiry_delta);
392394
}
393395

@@ -399,7 +401,8 @@ static void towire_route_info(u8 **pptr, const struct route_info *route_info)
399401
*
400402
* * `pubkey` (264 bits)
401403
* * `short_channel_id` (64 bits)
402-
* * `fee` (64 bits, big-endian)
404+
* * `fee_base_msat` (32 bits, big-endian)
405+
* * `fee_proportional_millionths` (32 bits, big-endian)
403406
* * `cltv_expiry_delta` (16 bits, big-endian)
404407
*/
405408
static char *decode_r(struct bolt11 *b11,

common/bolt11.h

+3-2
Original file line numberDiff line numberDiff line change
@@ -22,14 +22,15 @@ struct bolt11_field {
2222
/* BOLT #11:
2323
* * `pubkey` (264 bits)
2424
* * `short_channel_id` (64 bits)
25-
* * `fee` (64 bits, big-endian)
25+
* * `fee_base_msat` (32 bits, big-endian)
26+
* * `fee_proportional_millionths` (32 bits, big-endian)
2627
* * `cltv_expiry_delta` (16 bits, big-endian)
2728
*/
2829

2930
struct route_info {
3031
struct pubkey pubkey;
3132
struct short_channel_id short_channel_id;
32-
u64 fee;
33+
u32 fee_base_msat, fee_proportional_millionths;
3334
u16 cltv_expiry_delta;
3435
};
3536

common/test/run-bolt11.c

+6-6
Original file line numberDiff line numberDiff line change
@@ -17,9 +17,9 @@ void fromwire_short_channel_id(const u8 **cursor UNNEEDED, size_t *max UNNEEDED,
1717
/* Generated stub for fromwire_u16 */
1818
u16 fromwire_u16(const u8 **cursor UNNEEDED, size_t *max UNNEEDED)
1919
{ fprintf(stderr, "fromwire_u16 called!\n"); abort(); }
20-
/* Generated stub for fromwire_u64 */
21-
u64 fromwire_u64(const u8 **cursor UNNEEDED, size_t *max UNNEEDED)
22-
{ fprintf(stderr, "fromwire_u64 called!\n"); abort(); }
20+
/* Generated stub for fromwire_u32 */
21+
u32 fromwire_u32(const u8 **cursor UNNEEDED, size_t *max UNNEEDED)
22+
{ fprintf(stderr, "fromwire_u32 called!\n"); abort(); }
2323
/* Generated stub for towire_pubkey */
2424
void towire_pubkey(u8 **pptr UNNEEDED, const struct pubkey *pubkey UNNEEDED)
2525
{ fprintf(stderr, "towire_pubkey called!\n"); abort(); }
@@ -30,9 +30,9 @@ void towire_short_channel_id(u8 **pptr UNNEEDED,
3030
/* Generated stub for towire_u16 */
3131
void towire_u16(u8 **pptr UNNEEDED, u16 v UNNEEDED)
3232
{ fprintf(stderr, "towire_u16 called!\n"); abort(); }
33-
/* Generated stub for towire_u64 */
34-
void towire_u64(u8 **pptr UNNEEDED, u64 v UNNEEDED)
35-
{ fprintf(stderr, "towire_u64 called!\n"); abort(); }
33+
/* Generated stub for towire_u32 */
34+
void towire_u32(u8 **pptr UNNEEDED, u32 v UNNEEDED)
35+
{ fprintf(stderr, "towire_u32 called!\n"); abort(); }
3636
/* AUTOGENERATED MOCKS END */
3737

3838
static struct privkey privkey;

devtools/bolt11-cli.c

+3-2
Original file line numberDiff line numberDiff line change
@@ -142,12 +142,13 @@ int main(int argc, char *argv[])
142142
for (i = 0; i < tal_count(b11->routes); i++) {
143143
printf("route: (node/chanid/fee/expirydelta) ");
144144
for (size_t n = 0; n < tal_count(b11->routes[i]); n++) {
145-
printf(" %s/%s/%"PRIu64"/%u",
145+
printf(" %s/%s/%u/%u/%u",
146146
type_to_string(ctx, struct pubkey,
147147
&b11->routes[i][n].pubkey),
148148
type_to_string(ctx, struct short_channel_id,
149149
&b11->routes[i][n].short_channel_id),
150-
b11->routes[i][n].fee,
150+
b11->routes[i][n].fee_base_msat,
151+
b11->routes[i][n].fee_proportional_millionths,
151152
b11->routes[i][n].cltv_expiry_delta);
152153
}
153154
printf("\n");

lightningd/invoice.c

+4-2
Original file line numberDiff line numberDiff line change
@@ -547,8 +547,10 @@ static void json_decodepay(struct command *cmd,
547547
"short_channel_id",
548548
&b11->routes[i][n]
549549
.short_channel_id);
550-
json_add_u64(response, "fee",
551-
b11->routes[i][n].fee);
550+
json_add_u64(response, "fee_base_msat",
551+
b11->routes[i][n].fee_base_msat);
552+
json_add_u64(response, "fee_proportional_millionths",
553+
b11->routes[i][n].fee_proportional_millionths);
552554
json_add_num(response, "cltv_expiry_delta",
553555
b11->routes[i][n]
554556
.cltv_expiry_delta);

lightningd/test/run-find_my_path.c

+1-1
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,7 @@ void subd_shutdown(struct subd *subd UNNEEDED, unsigned int seconds UNNEEDED)
7979
void timer_expired(tal_t *ctx UNNEEDED, struct timer *timer UNNEEDED)
8080
{ fprintf(stderr, "timer_expired called!\n"); abort(); }
8181
/* Generated stub for txfilter_add_derkey */
82-
void txfilter_add_derkey(struct txfilter *filter UNNEEDED, u8 derkey[33])
82+
void txfilter_add_derkey(struct txfilter *filter UNNEEDED, u8 derkey[PUBKEY_DER_LEN])
8383
{ fprintf(stderr, "txfilter_add_derkey called!\n"); abort(); }
8484
/* Generated stub for txfilter_new */
8585
struct txfilter *txfilter_new(const tal_t *ctx UNNEEDED)

tests/test_lightningd.py

+13-10
Original file line numberDiff line numberDiff line change
@@ -464,7 +464,7 @@ def test_decodepay(self):
464464
assert b11['fallback']['addr'] == 'mk2QpYatsKicvFVuTAQLBryyccRXMUaGHP'
465465

466466
# > ### On mainnet, with fallback address 1RustyRX2oai4EYYDpQGWvEL62BBGqN9T with extra routing info to go via nodes 029e03a901b85534ff1e92c43c74431f7ce72046060fcf7a95c37e148f78c77255 then 039e03a901b85534ff1e92c43c74431f7ce72046060fcf7a95c37e148f78c77255
467-
# > lnbc20m1pvjluezpp5qqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqypqhp58yjmdan79s6qqdhdzgynm4zwqd5d7xmw5fk98klysy043l2ahrqsfpp3qjmp7lwpagxun9pygexvgpjdc4jdj85fr9yq20q82gphp2nflc7jtzrcazrra7wwgzxqc8u7754cdlpfrmccae92qgzqvzq2ps8pqqqqqqqqqqqq9qqqvpeuqafqxu92d8lr6fvg0r5gv0heeeqgcrqlnm6jhphu9y00rrhy4grqszsvpcgpy9qqqqqqqqqqqq7qqzqfnlkwydm8rg30gjku7wmxmk06sevjp53fmvrcfegvwy7d5443jvyhxsel0hulkstws7vqv400q4j3wgpk4crg49682hr4scqvmad43cqd5m7tf
467+
# > lnbc20m1pvjluezpp5qqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqypqhp58yjmdan79s6qqdhdzgynm4zwqd5d7xmw5fk98klysy043l2ahrqsfpp3qjmp7lwpagxun9pygexvgpjdc4jdj85fr9yq20q82gphp2nflc7jtzrcazrra7wwgzxqc8u7754cdlpfrmccae92qgzqvzq2ps8pqqqqqqpqqqqq9qqqvpeuqafqxu92d8lr6fvg0r5gv0heeeqgcrqlnm6jhphu9y00rrhy4grqszsvpcgpy9qqqqqqgqqqqq7qqzqj9n4evl6mr5aj9f58zp6fyjzup6ywn3x6sk8akg5v4tgn2q8g4fhx05wf6juaxu9760yp46454gpg5mtzgerlzezqcqvjnhjh8z3g2qqdhhwkj
468468
#
469469
# Breakdown:
470470
#
@@ -475,14 +475,15 @@ def test_decodepay(self):
475475
# * `p`: payment hash...
476476
# * `h`: tagged field: hash of description...
477477
# * `f`: tagged field: fallback address
478-
# * `pp`: `data_length` (`p` = 1. 1 * 32 + 1 == 33)
479-
# * `3qjmp7lwpagxun9pygexvgpjdc4jdj85f`: `3` = 17, so P2PKH address
478+
# * `pp`: `data_length` (`p` = 1. 1 * 32 + 1 == 33)
479+
# * `3` = 17, so P2PKH address
480+
# * `qjmp7lwpagxun9pygexvgpjdc4jdj85f`: 160 bit P2PKH address
480481
# * `r`: tagged field: route information
481-
# * `9y`: `data_length` (`9` = 5, `y` = 4. 5 * 32 + 4 = 164)
482-
# `q20q82gphp2nflc7jtzrcazrra7wwgzxqc8u7754cdlpfrmccae92qgzqvzq2ps8pqqqqqqqqqqqq9qqqvpeuqafqxu92d8lr6fvg0r5gv0heeeqgcrqlnm6jhphu9y00rrhy4grqszsvpcgpy9qqqqqqqqqqqq7qqzq`: pubkey `029e03a901b85534ff1e92c43c74431f7ce72046060fcf7a95c37e148f78c77255`, `short_channel_id` 0102030405060708, `fee` 20 millisatoshi, `cltv_expiry_delta` 3. pubkey `039e03a901b85534ff1e92c43c74431f7ce72046060fcf7a95c37e148f78c77255`, `short_channel_id` 030405060708090a, `fee` 30 millisatoshi, `cltv_expiry_delta` 4.
483-
# * `fnlkwydm8rg30gjku7wmxmk06sevjp53fmvrcfegvwy7d5443jvyhxsel0hulkstws7vqv400q4j3wgpk4crg49682hr4scqvmad43cq`: signature
484-
# * `d5m7tf`: Bech32 checksum
485-
b11 = l1.rpc.decodepay('lnbc20m1pvjluezpp5qqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqypqhp58yjmdan79s6qqdhdzgynm4zwqd5d7xmw5fk98klysy043l2ahrqsfpp3qjmp7lwpagxun9pygexvgpjdc4jdj85fr9yq20q82gphp2nflc7jtzrcazrra7wwgzxqc8u7754cdlpfrmccae92qgzqvzq2ps8pqqqqqqqqqqqq9qqqvpeuqafqxu92d8lr6fvg0r5gv0heeeqgcrqlnm6jhphu9y00rrhy4grqszsvpcgpy9qqqqqqqqqqqq7qqzqfnlkwydm8rg30gjku7wmxmk06sevjp53fmvrcfegvwy7d5443jvyhxsel0hulkstws7vqv400q4j3wgpk4crg49682hr4scqvmad43cqd5m7tf', 'One piece of chocolate cake, one icecream cone, one pickle, one slice of swiss cheese, one slice of salami, one lollypop, one piece of cherry pie, one sausage, one cupcake, and one slice of watermelon')
482+
# * `9y`: `data_length` (`9` = 5, `y` = 4. 5 * 32 + 4 = 164)
483+
# `q20q82gphp2nflc7jtzrcazrra7wwgzxqc8u7754cdlpfrmccae92qgzqvzq2ps8pqqqqqqqqqqqq9qqqvpeuqafqxu92d8lr6fvg0r5gv0heeeqgcrqlnm6jhphu9y00rrhy4grqszsvpcgpy9qqqqqqqqqqqq7qqzq`: pubkey `029e03a901b85534ff1e92c43c74431f7ce72046060fcf7a95c37e148f78c77255`, `short_channel_id` 0102030405060708, `fee_base_msat` 1 millisatoshi, `fee_proportional_millionths` 20, `cltv_expiry_delta` 3. pubkey `039e03a901b85534ff1e92c43c74431f7ce72046060fcf7a95c37e148f78c77255`, `short_channel_id` 030405060708090a, `fee_base_msat` 2 millisatoshi, `fee_proportional_millionths` 30, `cltv_expiry_delta` 4.
484+
# * `j9n4evl6mr5aj9f58zp6fyjzup6ywn3x6sk8akg5v4tgn2q8g4fhx05wf6juaxu9760yp46454gpg5mtzgerlzezqcqvjnhjh8z3g2qq`: signature
485+
# * `dhhwkj`: Bech32 checksum
486+
b11 = l1.rpc.decodepay('lnbc20m1pvjluezpp5qqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqypqhp58yjmdan79s6qqdhdzgynm4zwqd5d7xmw5fk98klysy043l2ahrqsfpp3qjmp7lwpagxun9pygexvgpjdc4jdj85fr9yq20q82gphp2nflc7jtzrcazrra7wwgzxqc8u7754cdlpfrmccae92qgzqvzq2ps8pqqqqqqpqqqqq9qqqvpeuqafqxu92d8lr6fvg0r5gv0heeeqgcrqlnm6jhphu9y00rrhy4grqszsvpcgpy9qqqqqqgqqqqq7qqzqj9n4evl6mr5aj9f58zp6fyjzup6ywn3x6sk8akg5v4tgn2q8g4fhx05wf6juaxu9760yp46454gpg5mtzgerlzezqcqvjnhjh8z3g2qqdhhwkj', 'One piece of chocolate cake, one icecream cone, one pickle, one slice of swiss cheese, one slice of salami, one lollypop, one piece of cherry pie, one sausage, one cupcake, and one slice of watermelon')
486487
assert b11['currency'] == 'bc'
487488
assert b11['msatoshi'] == 20 * 10**11 // 1000
488489
assert b11['timestamp'] == 1496314658
@@ -496,13 +497,15 @@ def test_decodepay(self):
496497
assert b11['routes'][0][0]['pubkey'] == '029e03a901b85534ff1e92c43c74431f7ce72046060fcf7a95c37e148f78c77255'
497498
# 0x010203:0x040506:0x0708
498499
assert b11['routes'][0][0]['short_channel_id'] == '66051:263430:1800'
499-
assert b11['routes'][0][0]['fee'] == 20
500+
assert b11['routes'][0][0]['fee_base_msat'] == 1
501+
assert b11['routes'][0][0]['fee_proportional_millionths'] == 20
500502
assert b11['routes'][0][0]['cltv_expiry_delta'] == 3
501503

502504
assert b11['routes'][0][1]['pubkey'] == '039e03a901b85534ff1e92c43c74431f7ce72046060fcf7a95c37e148f78c77255'
503505
# 0x030405:0x060708:0x090a
504506
assert b11['routes'][0][1]['short_channel_id'] == '197637:395016:2314'
505-
assert b11['routes'][0][1]['fee'] == 30
507+
assert b11['routes'][0][1]['fee_base_msat'] == 2
508+
assert b11['routes'][0][1]['fee_proportional_millionths'] == 30
506509
assert b11['routes'][0][1]['cltv_expiry_delta'] == 4
507510

508511
# > ### On mainnet, with fallback (P2SH) address 3EktnHQD7RiAE6uzMj2ZifT9YgRrkSgzQX

0 commit comments

Comments
 (0)