@@ -632,9 +632,32 @@ REGISTER_PAYMENT_MODIFIER(routehints, routehints_cb);
632632 * Compute the payment routes.
633633 */
634634
635- static struct command_result * compute_routes_cb (struct payment * payment )
635+ static bool json_to_myroute (const char * buf , const jsmntok_t * tok ,
636+ struct route * route )
637+ {
638+ u64 probability_ppm ;
639+ const char * err =
640+ json_scan (tmpctx , buf , tok , "{probability_ppm:%,amount_msat:%}" ,
641+ JSON_SCAN (json_to_u64 , & probability_ppm ),
642+ JSON_SCAN (json_to_msat , & route -> amount ));
643+ if (err )
644+ return false;
645+ route -> success_prob = probability_ppm * 1e-6 ;
646+ const jsmntok_t * path_tok = json_get_member (buf , tok , "path" );
647+ if (!path_tok || path_tok -> type != JSMN_ARRAY )
648+ return false;
649+ route -> hops = json_to_route (route , buf , path_tok );
650+ if (!route -> hops )
651+ return false;
652+ route -> amount_sent = route -> hops [0 ].amount ;
653+ return true;
654+ }
655+
656+ static struct command_result * getroutes_done (struct command * cmd UNUSED ,
657+ const char * buf ,
658+ const jsmntok_t * result ,
659+ struct payment * payment )
636660{
637- assert (payment -> status == PAYMENT_PENDING );
638661 struct routetracker * routetracker = payment -> routetracker ;
639662 assert (routetracker );
640663
@@ -643,7 +666,49 @@ static struct command_result *compute_routes_cb(struct payment *payment)
643666 plugin_err (pay_plugin -> plugin ,
644667 "%s: no previously computed routes expected." ,
645668 __func__ );
669+ routetracker -> computed_routes = tal_free (routetracker -> computed_routes );
670+
671+ const jsmntok_t * routes_tok = json_get_member (buf , result , "routes" );
672+ assert (routes_tok && routes_tok -> type == JSMN_ARRAY );
646673
674+ routetracker -> computed_routes =
675+ tal_arr (routetracker , struct route * , 0 );
676+
677+ size_t i ;
678+ const jsmntok_t * r ;
679+ json_for_each_arr (i , r , routes_tok )
680+ {
681+ struct route * route = new_route (
682+ routetracker -> computed_routes , payment -> groupid ,
683+ payment -> next_partid ++ , payment -> payment_info .payment_hash ,
684+ AMOUNT_MSAT (0 ), AMOUNT_MSAT (0 ));
685+ assert (route );
686+ tal_arr_expand (& routetracker -> computed_routes , route );
687+ bool success = json_to_myroute (buf , r , route );
688+ if (!success )
689+ plugin_err (pay_plugin -> plugin ,
690+ "%s: failed to parse route from json: %.*s" ,
691+ __func__ , json_tok_full_len (r ),
692+ json_tok_full (buf , r ));
693+ const size_t pathlen = tal_count (route -> hops );
694+ if (!amount_msat_eq (route -> amount ,
695+ route -> hops [pathlen - 1 ].amount ))
696+ plugin_log (pay_plugin -> plugin , LOG_UNUSUAL ,
697+ "%s: route partid=%" PRIu64
698+ " delivers %s which is different from what "
699+ "it claims to "
700+ "deliver %s" ,
701+ __func__ , route -> key .partid ,
702+ fmt_amount_msat (
703+ tmpctx , route -> hops [pathlen - 1 ].amount ),
704+ fmt_amount_msat (tmpctx , route -> amount ));
705+ }
706+ return payment_continue (payment );
707+ }
708+
709+ static struct command_result * compute_routes_cb (struct payment * payment )
710+ {
711+ assert (payment -> status == PAYMENT_PENDING );
647712 struct amount_msat feebudget , fees_spent , remaining ;
648713
649714 /* Total feebudget */
@@ -674,48 +739,25 @@ static struct command_result *compute_routes_cb(struct payment *payment)
674739 return payment_continue (payment );
675740 }
676741
677- enum jsonrpc_errcode errcode ;
678- const char * err_msg = NULL ;
679-
680- gossmap_apply_localmods (pay_plugin -> gossmap , payment -> local_gossmods );
681-
682- /* get_routes returns the answer, we assign it to the computed_routes,
683- * that's why we need to tal_free the older array. Maybe it would be
684- * better to pass computed_routes as a reference? */
685- routetracker -> computed_routes = tal_free (routetracker -> computed_routes );
686-
687- // TODO: add an algorithm selector here
688- /* We let this return an unlikely path, as it's better to try once than
689- * simply refuse. Plus, models are not truth! */
690- routetracker -> computed_routes = get_routes (
691- routetracker ,
692- & payment -> payment_info ,
693- & pay_plugin -> my_id ,
694- & payment -> payment_info .destination ,
695- pay_plugin -> gossmap ,
696- pay_plugin -> uncertainty ,
697- payment -> disabledmap ,
698- remaining ,
699- feebudget ,
700- & payment -> next_partid ,
701- payment -> groupid ,
702- & errcode ,
703- & err_msg );
704- /* Otherwise the error message remains a child of the routetracker. */
705- err_msg = tal_steal (tmpctx , err_msg );
706-
707- gossmap_remove_localmods (pay_plugin -> gossmap , payment -> local_gossmods );
708-
709- /* Couldn't feasible route, we stop. */
710- if (!routetracker -> computed_routes ||
711- tal_count (routetracker -> computed_routes ) == 0 ) {
712- if (err_msg == NULL )
713- err_msg = tal_fmt (
714- tmpctx , "get_routes returned NULL error message" );
715- return payment_fail (payment , errcode , "%s" , err_msg );
716- }
717-
718- return payment_continue (payment );
742+ struct command * cmd = payment_command (payment );
743+ assert (cmd );
744+ struct out_req * req =
745+ jsonrpc_request_start (cmd -> plugin , cmd , "getroutes" , getroutes_done ,
746+ payment_rpc_failure , payment );
747+ // FIXME: when multi-destination is needed to fully support blinded path
748+ // FIXME: we could have more than one algorithm to compute routes:
749+ // Minimum Cost Flows or the Max-Expected-Value (recently discussed with
750+ // Rene) or Dijkstra
751+ json_add_node_id (req -> js , "source" , & pay_plugin -> my_id );
752+ json_add_node_id (req -> js , "destination" ,
753+ & payment -> payment_info .destination );
754+ json_add_amount_msat (req -> js , "amount_msat" , remaining );
755+ json_array_start (req -> js , "layers" );
756+ // FIXME: put here the layers that we use
757+ json_array_end (req -> js );
758+ json_add_amount_msat (req -> js , "maxfee_msat" , feebudget );
759+ json_add_u32 (req -> js , "final_cltv" , payment -> payment_info .final_cltv );
760+ return send_outreq (cmd -> plugin , req );
719761}
720762
721763REGISTER_PAYMENT_MODIFIER (compute_routes , compute_routes_cb );
0 commit comments