@@ -632,9 +632,55 @@ 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+
650+ route -> hops = tal_arr (route , struct route_hop , path_tok -> size );
651+ if (!route -> hops )
652+ return false;
653+
654+ size_t i ;
655+ const jsmntok_t * hop_tok ;
656+ json_for_each_arr (i , hop_tok , path_tok )
657+ {
658+ struct route_hop * hop = & route -> hops [i ];
659+ err = json_scan (tmpctx , buf , hop_tok ,
660+ "{short_channel_id:%,direction:%,next_node_id:%"
661+ ",amount_msat:%,delay:%}" ,
662+ JSON_SCAN (json_to_short_channel_id , & hop -> scid ),
663+ JSON_SCAN (json_to_int , & hop -> direction ),
664+ JSON_SCAN (json_to_node_id , & hop -> node_id ),
665+ JSON_SCAN (json_to_msat , & hop -> amount ),
666+ JSON_SCAN (json_to_u32 , & hop -> delay ));
667+ if (err ) {
668+ route -> hops = tal_free (route -> hops );
669+ return false;
670+ }
671+ }
672+ route -> amount_sent = route -> hops [0 ].amount ;
673+ /* FIXME: it seems that the route we get in response claims to deliver
674+ * an amount which is different to the amount in the last hop. */
675+ route -> amount = route -> hops [path_tok -> size - 1 ].amount ;
676+ return true;
677+ }
678+
679+ static struct command_result * getroutes_done (struct command * cmd UNUSED ,
680+ const char * buf ,
681+ const jsmntok_t * result ,
682+ struct payment * payment )
636683{
637- assert (payment -> status == PAYMENT_PENDING );
638684 struct routetracker * routetracker = payment -> routetracker ;
639685 assert (routetracker );
640686
@@ -643,7 +689,49 @@ static struct command_result *compute_routes_cb(struct payment *payment)
643689 plugin_err (pay_plugin -> plugin ,
644690 "%s: no previously computed routes expected." ,
645691 __func__ );
692+ routetracker -> computed_routes = tal_free (routetracker -> computed_routes );
693+
694+ const jsmntok_t * routes_tok = json_get_member (buf , result , "routes" );
695+ assert (routes_tok && routes_tok -> type == JSMN_ARRAY );
696+
697+ routetracker -> computed_routes =
698+ tal_arr (routetracker , struct route * , 0 );
699+
700+ size_t i ;
701+ const jsmntok_t * r ;
702+ json_for_each_arr (i , r , routes_tok )
703+ {
704+ struct route * route = new_route (
705+ routetracker -> computed_routes , payment -> groupid ,
706+ payment -> next_partid ++ , payment -> payment_info .payment_hash ,
707+ AMOUNT_MSAT (0 ), AMOUNT_MSAT (0 ));
708+ assert (route );
709+ tal_arr_expand (& routetracker -> computed_routes , route );
710+ bool success = json_to_myroute (buf , r , route );
711+ if (!success )
712+ plugin_err (pay_plugin -> plugin ,
713+ "%s: failed to parse route from json: %.*s" ,
714+ __func__ , json_tok_full_len (r ),
715+ json_tok_full (buf , r ));
716+ const size_t pathlen = tal_count (route -> hops );
717+ if (!amount_msat_eq (route -> amount ,
718+ route -> hops [pathlen - 1 ].amount ))
719+ plugin_log (pay_plugin -> plugin , LOG_UNUSUAL ,
720+ "%s: route partid=%" PRIu64
721+ " delivers %s which is different from what "
722+ "it claims to "
723+ "deliver %s" ,
724+ __func__ , route -> key .partid ,
725+ fmt_amount_msat (
726+ tmpctx , route -> hops [pathlen - 1 ].amount ),
727+ fmt_amount_msat (tmpctx , route -> amount ));
728+ }
729+ return payment_continue (payment );
730+ }
646731
732+ static struct command_result * compute_routes_cb (struct payment * payment )
733+ {
734+ assert (payment -> status == PAYMENT_PENDING );
647735 struct amount_msat feebudget , fees_spent , remaining ;
648736
649737 /* Total feebudget */
@@ -674,48 +762,26 @@ static struct command_result *compute_routes_cb(struct payment *payment)
674762 return payment_continue (payment );
675763 }
676764
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 );
765+ struct command * cmd = payment_command (payment );
766+ assert (cmd );
767+ struct out_req * req =
768+ jsonrpc_request_start (cmd -> plugin , cmd , "getroutes" , getroutes_done ,
769+ payment_rpc_failure , payment );
770+ // FIXME: when multi-destination is needed to fully support blinded path
771+ // FIXME: we could have more than one algorithm to compute routes:
772+ // Minimum Cost Flows or the Max-Expected-Value (recently discussed with
773+ // Rene) or Dijkstra
774+ json_add_node_id (req -> js , "source" , & pay_plugin -> my_id );
775+ json_add_node_id (req -> js , "destination" ,
776+ & payment -> payment_info .destination );
777+ json_add_amount_msat (req -> js , "amount_msat" , remaining );
778+ json_array_start (req -> js , "layers" );
779+ // FIXME: put here the layers that we use
780+ json_add_string (req -> js , NULL , "auto.localchans" );
781+ json_array_end (req -> js );
782+ json_add_amount_msat (req -> js , "maxfee_msat" , feebudget );
783+ json_add_u32 (req -> js , "final_cltv" , payment -> payment_info .final_cltv );
784+ return send_outreq (cmd -> plugin , req );
719785}
720786
721787REGISTER_PAYMENT_MODIFIER (compute_routes , compute_routes_cb );
0 commit comments