| 324 | } |
| 325 | |
| 326 | struct tlv_invoice_request *invrequest_decode(const tal_t *ctx, |
| 327 | const char *b12, size_t b12len, |
| 328 | const struct feature_set *our_features, |
| 329 | const struct chainparams *must_be_chain, |
| 330 | const char **fail) |
| 331 | { |
| 332 | struct tlv_invoice_request *invrequest; |
| 333 | const u8 *data; |
| 334 | size_t dlen; |
| 335 | const struct tlv_field *badf; |
| 336 | |
| 337 | data = b12_string_to_data(tmpctx, b12, b12len, "lnr", &dlen, fail); |
| 338 | if (!data) { |
| 339 | tal_steal(ctx, *fail); |
| 340 | return NULL; |
| 341 | } |
| 342 | |
| 343 | invrequest = fromwire_tlv_invoice_request(ctx, &data, &dlen); |
| 344 | if (!invrequest) { |
| 345 | *fail = tal_fmt(ctx, "invalid invreq data"); |
| 346 | return NULL; |
| 347 | } |
| 348 | |
| 349 | *fail = check_features_and_chain(ctx, |
| 350 | our_features, must_be_chain, |
| 351 | invrequest->invreq_features, |
| 352 | BOLT12_INVREQ_FEATURE, |
| 353 | invrequest->invreq_chain, 1); |
| 354 | if (*fail) |
| 355 | return tal_free(invrequest); |
| 356 | |
| 357 | /* BOLT #12: |
| 358 | * The reader: |
| 359 | *... |
| 360 | * - MUST reject the invoice request if any non-signature TLV fields are outside the inclusive ranges: 0 to 159 and 1000000000 to 2999999999 |
| 361 | */ |
| 362 | badf = any_field_outside_range(invrequest->fields, true, |
| 363 | 0, 159, |
| 364 | 1000000000, 2999999999); |
| 365 | if (badf) { |
| 366 | *fail = tal_fmt(ctx, |
| 367 | "Invoice request %"PRIu64" field outside invoice request range", |
| 368 | badf->numtype); |
| 369 | return tal_free(invrequest); |
| 370 | } |
| 371 | |
| 372 | /* BOLT #12: |
| 373 | * - if `num_hops` is 0 in any `blinded_path` in `invreq_paths`: |
| 374 | * - MUST reject the invoice request. |
| 375 | */ |
| 376 | for (size_t i = 0; i < tal_count(invrequest->invreq_paths); i++) { |
| 377 | if (tal_count(invrequest->invreq_paths[i]->path) == 0) { |
| 378 | *fail = tal_strdup(ctx, "Invoice request contains an empty invreq_path"); |
| 379 | return tal_free(invrequest); |
| 380 | } |
| 381 | } |
| 382 | |
| 383 | return invrequest; |