diff --git a/lightningd/bolt11.c b/lightningd/bolt11.c index d7933f311..d73225868 100644 --- a/lightningd/bolt11.c +++ b/lightningd/bolt11.c @@ -248,6 +248,33 @@ static char *decode_x(struct bolt11 *b11, return NULL; } +/* BOLT #11: + * + * `c` (24): `data_length` variable. `min_final_cltv_expiry` to use for the + * last HTLC in the route. Default is 9 if not specified. + */ +#define DEFAULT_C 9 +static char *decode_c(struct bolt11 *b11, + struct hash_u5 *hu5, + u5 **data, size_t *data_len, + size_t data_length, bool *have_c) +{ + u64 c; + if (*have_c) + return unknown_field(b11, hu5, data, data_len, 'c', + data_length); + + /* FIXME: Put upper limit in bolt 11 */ + if (!pull_uint(hu5, data, data_len, &c, data_length * 5)) + return tal_fmt(b11, "c: length %zu chars is excessive", + *data_len); + b11->min_final_cltv_expiry = c; + if (b11->min_final_cltv_expiry != c) + return tal_fmt(b11, "c: %"PRIu64" is too large", c); + + return NULL; +} + static char *decode_n(struct bolt11 *b11, struct hash_u5 *hu5, u5 **data, size_t *data_len, @@ -417,6 +444,8 @@ struct bolt11 *new_bolt11(const tal_t *ctx, u64 *msatoshi) b11->fallback = NULL; b11->routes = NULL; b11->msatoshi = NULL; + b11->expiry = DEFAULT_X; + b11->min_final_cltv_expiry = DEFAULT_C; if (msatoshi) b11->msatoshi = tal_dup(b11, u64, msatoshi); @@ -437,7 +466,7 @@ struct bolt11 *bolt11_decode(const tal_t *ctx, const char *str, struct hash_u5 hu5; struct sha256 hash; bool have_p = false, have_n = false, have_d = false, have_h = false, - have_x = false, have_f = false; + have_x = false, have_f = false, have_c = false; b11->routes = tal_arr(b11, struct route_info *, 0); @@ -528,8 +557,6 @@ struct bolt11 *bolt11_decode(const tal_t *ctx, const char *str, if (!pull_uint(&hu5, &data, &data_len, &b11->timestamp, 35)) return decode_fail(b11, fail, "Can't get 35-bit timestamp"); - b11->expiry = DEFAULT_X; - while (data_len > 520 / 5) { const char *problem = NULL; u64 type, data_length; @@ -580,6 +607,12 @@ struct bolt11 *bolt11_decode(const tal_t *ctx, const char *str, &have_x); break; + case 'c': + problem = decode_c(b11, &hu5, &data, + &data_len, data_length, + &have_c); + break; + case 'f': problem = decode_f(b11, &hu5, &data, &data_len, data_length, @@ -765,6 +798,11 @@ static void encode_x(u5 **data, u64 expiry) push_varlen_field(data, 'x', expiry); } +static void encode_c(u5 **data, u16 min_final_cltv_expiry) +{ + push_varlen_field(data, 'c', min_final_cltv_expiry); +} + static void encode_f(u5 **data, const u8 *fallback) { struct bitcoin_address pkh; @@ -906,6 +944,9 @@ char *bolt11_encode(const tal_t *ctx, if (b11->expiry != DEFAULT_X) encode_x(&data, b11->expiry); + if (b11->min_final_cltv_expiry != DEFAULT_C) + encode_c(&data, b11->min_final_cltv_expiry); + if (b11->fallback) encode_f(&data, b11->fallback); diff --git a/lightningd/bolt11.h b/lightningd/bolt11.h index af0296224..73b0a9802 100644 --- a/lightningd/bolt11.h +++ b/lightningd/bolt11.h @@ -49,6 +49,9 @@ struct bolt11 { /* How many seconds to pay from @timestamp above. */ u64 expiry; + /* How many blocks final hop requires. */ + u32 min_final_cltv_expiry; + /* If non-NULL, indicates a fallback address to pay to. */ const u8 *fallback; diff --git a/lightningd/invoice.c b/lightningd/invoice.c index 5aa4029fc..955de5180 100644 --- a/lightningd/invoice.c +++ b/lightningd/invoice.c @@ -181,6 +181,7 @@ static void json_invoice(struct command *cmd, b11->timestamp = time_now().ts.tv_sec; b11->payment_hash = invoice->rhash; b11->receiver_id = cmd->ld->id; + b11->min_final_cltv_expiry = cmd->ld->config.cltv_final; if (desc->end - desc->start >= BOLT11_FIELD_BYTE_LIMIT) { b11->description_hash = tal(b11, struct sha256); sha256(b11->description_hash, buffer + desc->start, @@ -188,8 +189,7 @@ static void json_invoice(struct command *cmd, } else b11->description = tal_strndup(b11, buffer + desc->start, desc->end - desc->start); - /* FIXME: add option to set this */ - b11->expiry = 3600; + /* FIXME: add option to set expiry */ /* FIXME: add private routes if necessary! */ b11enc = bolt11_encode(cmd, cmd->ld, b11, false); diff --git a/lightningd/pay.c b/lightningd/pay.c index 6ec0bec8d..66e63e4bb 100644 --- a/lightningd/pay.c +++ b/lightningd/pay.c @@ -393,8 +393,6 @@ static void json_pay(struct command *cmd, jsmntok_t *bolt11tok, *msatoshitok, *desctok, *riskfactortok; double riskfactor = 1.0; u64 msatoshi; - /* FIXME: add ctlv to bolt11 */ - u32 cltv = 9; struct pay *pay = tal(cmd, struct pay); struct bolt11 *b11; char *fail, *b11str, *desc; @@ -458,7 +456,8 @@ static void json_pay(struct command *cmd, /* FIXME: use b11->routes */ req = towire_gossip_getroute_request(cmd, &cmd->ld->id, &b11->receiver_id, - msatoshi, riskfactor*1000, cltv); + msatoshi, riskfactor*1000, + b11->min_final_cltv_expiry); subd_req(pay, cmd->ld->gossip, req, -1, 0, json_pay_getroute_reply, pay); }