@@ -331,60 +331,35 @@ const char *fmt_flow_full(const tal_t *ctx,
331
331
return str ;
332
332
}
333
333
334
- /* Returns an error message, or sets *routes */
335
- static const char * get_routes (const tal_t * ctx ,
336
- struct command * cmd ,
337
- const struct node_id * source ,
338
- const struct node_id * dest ,
339
- struct amount_msat amount ,
340
- struct amount_msat maxfee ,
341
- u32 finalcltv ,
342
- u32 maxdelay ,
343
- const char * * layers ,
344
- struct gossmap_localmods * localmods ,
345
- const struct layer * local_layer ,
346
- bool single_path ,
347
- struct route * * * routes ,
348
- struct amount_msat * * amounts ,
349
- const struct additional_cost_htable * additional_costs ,
350
- double * probability )
351
- {
352
- struct askrene * askrene = get_askrene (cmd -> plugin );
353
- struct route_query * rq = tal (ctx , struct route_query );
354
- struct flow * * flows ;
355
- const struct gossmap_node * srcnode , * dstnode ;
356
- const char * ret ;
357
- struct timerel time_delta ;
358
- struct timemono time_start = time_mono ();
359
-
360
- if (gossmap_refresh (askrene -> gossmap )) {
361
- /* FIXME: gossmap_refresh callbacks to we can update in place */
362
- tal_free (askrene -> capacities );
363
- askrene -> capacities = get_capacities (askrene , askrene -> plugin , askrene -> gossmap );
364
- }
365
-
366
- rq -> cmd = cmd ;
367
- rq -> plugin = cmd -> plugin ;
368
- rq -> gossmap = askrene -> gossmap ;
369
- rq -> reserved = askrene -> reserved ;
370
- rq -> layers = tal_arr (rq , const struct layer * , 0 );
371
- rq -> capacities = tal_dup_talarr (rq , fp16_t , askrene -> capacities );
372
- rq -> additional_costs = additional_costs ;
334
+ struct getroutes_info {
335
+ struct command * cmd ;
336
+ struct node_id * source , * dest ;
337
+ struct amount_msat * amount , * maxfee ;
338
+ u32 * finalcltv , * maxdelay ;
339
+ const char * * layers ;
340
+ struct additional_cost_htable * additional_costs ;
341
+ /* Non-NULL if we are told to use "auto.localchans" */
342
+ struct layer * local_layer ;
343
+ };
373
344
345
+ static void apply_layers (struct askrene * askrene , struct route_query * rq ,
346
+ struct gossmap_localmods * localmods ,
347
+ const struct getroutes_info * info )
348
+ {
374
349
/* Layers must exist, but might be special ones! */
375
- for (size_t i = 0 ; i < tal_count (layers ); i ++ ) {
376
- const struct layer * l = find_layer (askrene , layers [i ]);
350
+ for (size_t i = 0 ; i < tal_count (info -> layers ); i ++ ) {
351
+ const struct layer * l = find_layer (askrene , info -> layers [i ]);
377
352
if (!l ) {
378
- if (streq (layers [i ], "auto.localchans" )) {
353
+ if (streq (info -> layers [i ], "auto.localchans" )) {
379
354
plugin_log (rq -> plugin , LOG_DBG , "Adding auto.localchans" );
380
- l = local_layer ;
381
- } else if (streq (layers [i ], "auto.no_mpp_support" )) {
355
+ l = info -> local_layer ;
356
+ } else if (streq (info -> layers [i ], "auto.no_mpp_support" )) {
382
357
plugin_log (rq -> plugin , LOG_DBG , "Adding auto.no_mpp_support, sorry" );
383
- l = remove_small_channel_layer (layers , askrene , amount , localmods );
358
+ l = remove_small_channel_layer (info -> layers , askrene , * info -> amount , localmods );
384
359
} else {
385
- assert (streq (layers [i ], "auto.sourcefree" ));
360
+ assert (streq (info -> layers [i ], "auto.sourcefree" ));
386
361
plugin_log (rq -> plugin , LOG_DBG , "Adding auto.sourcefree" );
387
- l = source_free_layer (layers , askrene , source , localmods );
362
+ l = source_free_layer (info -> layers , askrene , info -> source , localmods );
388
363
}
389
364
}
390
365
@@ -396,46 +371,14 @@ static const char *get_routes(const tal_t *ctx,
396
371
* override them (incl local channels) */
397
372
layer_clear_overridden_capacities (l , askrene -> gossmap , rq -> capacities );
398
373
}
374
+ }
399
375
400
- /* Clear scids with reservations, too, so we don't have to look up
401
- * all the time! */
402
- reserves_clear_capacities (askrene -> reserved , askrene -> gossmap , rq -> capacities );
403
-
404
- gossmap_apply_localmods (askrene -> gossmap , localmods );
405
-
406
- /* localmods can add channels, so we need to allocate biases array *afterwards* */
407
- rq -> biases = tal_arrz (rq , s8 , gossmap_max_chan_idx (askrene -> gossmap ) * 2 );
408
-
409
- /* Note any channel biases */
410
- for (size_t i = 0 ; i < tal_count (rq -> layers ); i ++ )
411
- layer_apply_biases (rq -> layers [i ], askrene -> gossmap , rq -> biases );
412
-
413
- srcnode = gossmap_find_node (askrene -> gossmap , source );
414
- if (!srcnode ) {
415
- ret = rq_log (ctx , rq , LOG_INFORM ,
416
- "Unknown source node %s" ,
417
- fmt_node_id (tmpctx , source ));
418
- goto fail ;
419
- }
420
-
421
- dstnode = gossmap_find_node (askrene -> gossmap , dest );
422
- if (!dstnode ) {
423
- ret = rq_log (ctx , rq , LOG_INFORM ,
424
- "Unknown destination node %s" ,
425
- fmt_node_id (tmpctx , dest ));
426
- goto fail ;
427
- }
428
-
429
- /* FIXME: single_path should signal a change in algorithm. */
430
- ret = default_routes (rq , rq , srcnode , dstnode , amount , single_path ,
431
- maxfee , finalcltv , maxdelay , & flows , probability );
432
- if (ret ) {
433
- goto fail ;
434
- }
435
- assert (tal_count (flows ) > 0 );
436
- rq_log (tmpctx , rq , LOG_DBG , "Final answer has %zu flows" ,
437
- tal_count (flows ));
438
-
376
+ static void convert_flows_to_routes (const tal_t * ctx , struct route_query * rq ,
377
+ struct route * * * routes ,
378
+ struct amount_msat * * amounts ,
379
+ u32 finalcltv ,
380
+ struct flow * * flows )
381
+ {
439
382
/* Convert back into routes, with delay and other information fixed */
440
383
* routes = tal_arr (ctx , struct route * , tal_count (flows ));
441
384
* amounts = tal_arr (ctx , struct amount_msat , tal_count (flows ));
@@ -473,22 +416,6 @@ static const char *get_routes(const tal_t *ctx,
473
416
i , tal_count (flows ),
474
417
fmt_route (tmpctx , r , (* amounts )[i ], finalcltv ));
475
418
}
476
-
477
- gossmap_remove_localmods (askrene -> gossmap , localmods );
478
- time_delta = timemono_between (time_mono (), time_start );
479
- rq_log (tmpctx , rq , LOG_DBG , "get_routes completed in %" PRIu64 " ms" ,
480
- time_to_msec (time_delta ));
481
- return NULL ;
482
-
483
- /* Explicit failure path keeps the compiler (gcc version 12.3.0 -O3) from
484
- * warning about uninitialized variables in the caller */
485
- fail :
486
- assert (ret != NULL );
487
- gossmap_remove_localmods (askrene -> gossmap , localmods );
488
- time_delta = timemono_between (time_mono (), time_start );
489
- rq_log (tmpctx , rq , LOG_DBG , "get_routes failed after %" PRIu64 " ms" ,
490
- time_to_msec (time_delta ));
491
- return ret ;
492
419
}
493
420
494
421
void get_constraints (const struct route_query * rq ,
@@ -527,16 +454,40 @@ void get_constraints(const struct route_query *rq,
527
454
reserve_sub (rq -> reserved , & scidd , max );
528
455
}
529
456
530
- struct getroutes_info {
531
- struct command * cmd ;
532
- struct node_id * source , * dest ;
533
- struct amount_msat * amount , * maxfee ;
534
- u32 * finalcltv , * maxdelay ;
535
- const char * * layers ;
536
- struct additional_cost_htable * additional_costs ;
537
- /* Non-NULL if we are told to use "auto.localchans" */
538
- struct layer * local_layer ;
539
- };
457
+ static void json_add_getroutes (
458
+ struct json_stream * js ,
459
+ struct route * * routes ,
460
+ const struct amount_msat * amounts ,
461
+ double probability ,
462
+ u32 final_cltv )
463
+ {
464
+ json_add_u64 (js , "probability_ppm" , (u64 )(probability * 1000000 ));
465
+ json_array_start (js , "routes" );
466
+ for (size_t i = 0 ; i < tal_count (routes ); i ++ ) {
467
+ json_object_start (js , NULL );
468
+ json_add_u64 (js , "probability_ppm" ,
469
+ (u64 )(routes [i ]-> success_prob * 1000000 ));
470
+ json_add_amount_msat (js , "amount_msat" , amounts [i ]);
471
+ json_add_u32 (js , "final_cltv" , final_cltv );
472
+ json_array_start (js , "path" );
473
+ for (size_t j = 0 ; j < tal_count (routes [i ]-> hops ); j ++ ) {
474
+ struct short_channel_id_dir scidd ;
475
+ const struct route_hop * r = & routes [i ]-> hops [j ];
476
+ json_object_start (js , NULL );
477
+ scidd .scid = r -> scid ;
478
+ scidd .dir = r -> direction ;
479
+ json_add_short_channel_id_dir (
480
+ js , "short_channel_id_dir" , scidd );
481
+ json_add_node_id (js , "next_node_id" , & r -> node_id );
482
+ json_add_amount_msat (js , "amount_msat" , r -> amount );
483
+ json_add_u32 (js , "delay" , r -> delay );
484
+ json_object_end (js );
485
+ }
486
+ json_array_end (js );
487
+ json_object_end (js );
488
+ }
489
+ json_array_end (js );
490
+ }
540
491
541
492
static struct command_result * do_getroutes (struct command * cmd ,
542
493
struct gossmap_localmods * localmods ,
@@ -546,43 +497,111 @@ static struct command_result *do_getroutes(struct command *cmd,
546
497
double probability ;
547
498
struct amount_msat * amounts ;
548
499
struct route * * routes ;
500
+ struct flow * * flows ;
549
501
struct json_stream * response ;
550
502
551
- err = get_routes (cmd , cmd ,
552
- info -> source , info -> dest ,
553
- * info -> amount , * info -> maxfee , * info -> finalcltv ,
554
- * info -> maxdelay , info -> layers , localmods , info -> local_layer ,
555
- have_layer (info -> layers , "auto.no_mpp_support" ),
556
- & routes , & amounts , info -> additional_costs , & probability );
503
+ /* get me the global state structure */
504
+ struct askrene * askrene = get_askrene (cmd -> plugin );
505
+
506
+ /* update the gossmap */
507
+ if (gossmap_refresh (askrene -> gossmap )) {
508
+ /* FIXME: gossmap_refresh callbacks to we can update in place */
509
+ tal_free (askrene -> capacities );
510
+ askrene -> capacities =
511
+ get_capacities (askrene , askrene -> plugin , askrene -> gossmap );
512
+ }
513
+
514
+ /* build this request structure */
515
+ struct route_query * rq = tal (cmd , struct route_query );
516
+ rq -> cmd = cmd ;
517
+ rq -> plugin = cmd -> plugin ;
518
+ rq -> gossmap = askrene -> gossmap ;
519
+ rq -> reserved = askrene -> reserved ;
520
+ rq -> layers = tal_arr (rq , const struct layer * , 0 );
521
+ rq -> capacities = tal_dup_talarr (rq , fp16_t , askrene -> capacities );
522
+ /* FIXME: we still need to do something useful with these */
523
+ rq -> additional_costs = info -> additional_costs ;
524
+
525
+ /* apply selected layers to the localmods */
526
+ apply_layers (askrene , rq , localmods , info );
527
+
528
+ /* Clear scids with reservations, too, so we don't have to look up
529
+ * all the time! */
530
+ reserves_clear_capacities (askrene -> reserved , askrene -> gossmap ,
531
+ rq -> capacities );
532
+
533
+ /* we temporarily apply localmods */
534
+ gossmap_apply_localmods (askrene -> gossmap , localmods );
535
+
536
+ /* localmods can add channels, so we need to allocate biases array
537
+ * *afterwards* */
538
+ rq -> biases =
539
+ tal_arrz (rq , s8 , gossmap_max_chan_idx (askrene -> gossmap ) * 2 );
540
+
541
+ /* Note any channel biases */
542
+ for (size_t i = 0 ; i < tal_count (rq -> layers ); i ++ )
543
+ layer_apply_biases (rq -> layers [i ], askrene -> gossmap , rq -> biases );
544
+
545
+ /* checkout the source */
546
+ const struct gossmap_node * srcnode =
547
+ gossmap_find_node (askrene -> gossmap , info -> source );
548
+ if (!srcnode ) {
549
+ err = rq_log (tmpctx , rq , LOG_INFORM , "Unknown source node %s" ,
550
+ fmt_node_id (tmpctx , info -> source ));
551
+ goto fail ;
552
+ }
553
+
554
+ /* checkout the destination */
555
+ const struct gossmap_node * dstnode =
556
+ gossmap_find_node (askrene -> gossmap , info -> dest );
557
+ if (!dstnode ) {
558
+ err = rq_log (tmpctx , rq , LOG_INFORM ,
559
+ "Unknown destination node %s" ,
560
+ fmt_node_id (tmpctx , info -> dest ));
561
+ goto fail ;
562
+ }
563
+
564
+ /* Compute the routes. At this point we might select between multiple
565
+ * algorithms. */
566
+ struct timemono time_start = time_mono ();
567
+ err = default_routes (rq , rq , srcnode , dstnode , * info -> amount ,
568
+ /* only one path? = */
569
+ have_layer (info -> layers , "auto.no_mpp_support" ),
570
+ * info -> maxfee , * info -> finalcltv , * info -> maxdelay ,
571
+ & flows , & probability );
572
+ struct timerel time_delta = timemono_between (time_mono (), time_start );
573
+
574
+ /* log the time of computation */
575
+ rq_log (tmpctx , rq , LOG_DBG , "get_routes %s %" PRIu64 " ms" ,
576
+ err ? "failed after" : "completed in" ,
577
+ time_to_msec (time_delta ));
557
578
if (err )
558
- return command_fail ( cmd , PAY_ROUTE_NOT_FOUND , "%s" , err ) ;
579
+ goto fail ;
559
580
581
+ /* otherwise we continue */
582
+ assert (tal_count (flows ) > 0 );
583
+ rq_log (tmpctx , rq , LOG_DBG , "Final answer has %zu flows" ,
584
+ tal_count (flows ));
585
+
586
+ /* convert flows to routes */
587
+ convert_flows_to_routes (rq , rq , & routes , & amounts , * info -> finalcltv ,
588
+ flows );
589
+ assert (tal_count (routes ) == tal_count (flows ));
590
+ assert (tal_count (amounts ) == tal_count (flows ));
591
+
592
+ /* At last we remove the localmods from the gossmap. */
593
+ gossmap_remove_localmods (askrene -> gossmap , localmods );
594
+
595
+ /* output the results */
560
596
response = jsonrpc_stream_success (cmd );
561
- json_add_u64 (response , "probability_ppm" , (u64 )(probability * 1000000 ));
562
- json_array_start (response , "routes" );
563
- for (size_t i = 0 ; i < tal_count (routes ); i ++ ) {
564
- json_object_start (response , NULL );
565
- json_add_u64 (response , "probability_ppm" , (u64 )(routes [i ]-> success_prob * 1000000 ));
566
- json_add_amount_msat (response , "amount_msat" , amounts [i ]);
567
- json_add_u32 (response , "final_cltv" , * info -> finalcltv );
568
- json_array_start (response , "path" );
569
- for (size_t j = 0 ; j < tal_count (routes [i ]-> hops ); j ++ ) {
570
- struct short_channel_id_dir scidd ;
571
- const struct route_hop * r = & routes [i ]-> hops [j ];
572
- json_object_start (response , NULL );
573
- scidd .scid = r -> scid ;
574
- scidd .dir = r -> direction ;
575
- json_add_short_channel_id_dir (response , "short_channel_id_dir" , scidd );
576
- json_add_node_id (response , "next_node_id" , & r -> node_id );
577
- json_add_amount_msat (response , "amount_msat" , r -> amount );
578
- json_add_u32 (response , "delay" , r -> delay );
579
- json_object_end (response );
580
- }
581
- json_array_end (response );
582
- json_object_end (response );
583
- }
584
- json_array_end (response );
597
+ json_add_getroutes (response , routes , amounts , probability ,
598
+ * info -> finalcltv );
585
599
return command_finished (cmd , response );
600
+
601
+ fail :
602
+ assert (err );
603
+ gossmap_remove_localmods (askrene -> gossmap , localmods );
604
+ return command_fail (cmd , PAY_ROUTE_NOT_FOUND , "%s" , err );
586
605
}
587
606
588
607
static void add_localchan (struct gossmap_localmods * mods ,
0 commit comments