@@ -52,6 +52,13 @@ struct xpay {
5252 /* Suppress calls to askrene-age */
5353 bool dev_no_age ;
5454 const char * * user_layers ;
55+ /* We cannot initialize xpay with rpc_scan, we use instead asynchronous
56+ * requests to fetch the node_id, the blockheight and create the xpay
57+ * layer in askrene. Hence we need a flag to signal when we are ready
58+ * for processing payments otherwise we get a race condition: a payment
59+ * arrives and we don't know our own node_id yet, for example. In
60+ * practice this will be more useful for tests. */
61+ bool ready ;
5562};
5663
5764static struct xpay * xpay_of (struct plugin * plugin )
@@ -2303,6 +2310,7 @@ static struct command_result *json_xpay_params(struct command *cmd,
23032310 const jsmntok_t * params ,
23042311 bool as_pay )
23052312{
2313+ struct xpay * xpay = xpay_of (cmd -> plugin );
23062314 struct amount_msat * msat , * maxfee , * partial ;
23072315 const char * invstring ;
23082316 const char * * layers ;
@@ -2329,6 +2337,8 @@ static struct command_result *json_xpay_params(struct command *cmd,
23292337 p_opt_dev ("dev_use_shadow" , param_bool , & dev_use_shadow , true),
23302338 NULL ))
23312339 return command_param_failed ();
2340+ if (!xpay -> ready )
2341+ return command_fail (cmd , PLUGIN_ERROR , "xpay is initializing" );
23322342
23332343 /* Is this a one-shot vibe payment? Kids these days! */
23342344 if (!as_pay && bolt12_has_offer_prefix (invstring )) {
@@ -2514,6 +2524,8 @@ bool attempt_ongoing(struct plugin *plugin, const struct sha256 *payment_hash,
25142524 u64 groupid )
25152525{
25162526 struct xpay * xpay = xpay_of (plugin );
2527+ if (!xpay -> ready )
2528+ return false;
25172529 const struct payment * payment ;
25182530
25192531 list_for_each (& xpay -> payments , payment , list ) {
@@ -2817,6 +2829,7 @@ static struct command_result *json_sendamount(struct command *cmd,
28172829 const char * buffer ,
28182830 const jsmntok_t * params )
28192831{
2832+ struct xpay * xpay = xpay_of (cmd -> plugin );
28202833 struct amount_msat * send_msat , * maxfee ;
28212834 struct amount_msat invoice_msat ;
28222835 const char * invstring ;
@@ -2839,6 +2852,8 @@ static struct command_result *json_sendamount(struct command *cmd,
28392852 p_opt ("label" , param_label , & label ),
28402853 NULL ))
28412854 return command_param_failed ();
2855+ if (!xpay -> ready )
2856+ return command_fail (cmd , PLUGIN_ERROR , "xpay is initializing" );
28422857
28432858 // FIXME: why does xpay returns this only after
28442859 // preapproveinvoice_succeed?
@@ -2903,21 +2918,15 @@ static struct command_result *json_sendamount(struct command *cmd,
29032918 label , NULL , false, false, send_msat );
29042919}
29052920
2906- static struct command_result * getchaininfo_done (struct command * aux_cmd ,
2907- const char * method ,
2908- const char * buf ,
2909- const jsmntok_t * result ,
2910- void * unused )
2921+ static struct command_result * xpay_layer_created (struct command * aux_cmd ,
2922+ const char * method ,
2923+ const char * buf ,
2924+ const jsmntok_t * result ,
2925+ void * unused )
29112926{
29122927 struct xpay * xpay = xpay_of (aux_cmd -> plugin );
2913-
2914- /* We use headercount from the backend, in case we're still syncing */
2915- if (!json_to_u32 (buf , json_get_member (buf , result , "headercount" ),
2916- & xpay -> blockheight )) {
2917- plugin_err (aux_cmd -> plugin , "Bad getchaininfo '%.*s'" ,
2918- json_tok_full_len (result ),
2919- json_tok_full (buf , result ));
2920- }
2928+ xpay -> ready = true;
2929+ plugin_log (aux_cmd -> plugin , LOG_INFORM , "xpay is ready" );
29212930 return aux_command_done (aux_cmd );
29222931}
29232932
@@ -2929,6 +2938,7 @@ static struct command_result *getinfo_done(struct command *aux_cmd,
29292938{
29302939 struct xpay * xpay = xpay_of (aux_cmd -> plugin );
29312940 const char * err ;
2941+ struct out_req * req ;
29322942
29332943 err = json_scan (tmpctx , buf , result ,
29342944 "{id:%}" , JSON_SCAN (json_to_pubkey , & xpay -> local_id ));
@@ -2938,7 +2948,35 @@ static struct command_result *getinfo_done(struct command *aux_cmd,
29382948 json_tok_full (buf , result ),
29392949 err );
29402950 }
2941- return aux_command_done (aux_cmd );
2951+
2952+ req = jsonrpc_request_start (aux_cmd , "askrene-create-layer" ,
2953+ xpay_layer_created , plugin_broken_cb ,
2954+ "askrene-create-layer" );
2955+ json_add_string (req -> js , "layer" , "xpay" );
2956+ json_add_bool (req -> js , "persistent" , true);
2957+ return send_outreq (req );
2958+ }
2959+
2960+ static struct command_result * getchaininfo_done (struct command * aux_cmd ,
2961+ const char * method ,
2962+ const char * buf ,
2963+ const jsmntok_t * result ,
2964+ void * unused )
2965+ {
2966+ struct xpay * xpay = xpay_of (aux_cmd -> plugin );
2967+ struct out_req * req ;
2968+
2969+ /* We use headercount from the backend, in case we're still syncing */
2970+ if (!json_to_u32 (buf , json_get_member (buf , result , "headercount" ),
2971+ & xpay -> blockheight )) {
2972+ plugin_err (aux_cmd -> plugin , "Bad getchaininfo '%.*s'" ,
2973+ json_tok_full_len (result ),
2974+ json_tok_full (buf , result ));
2975+ }
2976+
2977+ req = jsonrpc_request_start (aux_cmd , "getinfo" , getinfo_done ,
2978+ plugin_broken_cb , "getinfo" );
2979+ return send_outreq (req );
29422980}
29432981
29442982static struct command_result * populate_private_layer (struct command * cmd ,
@@ -2970,15 +3008,6 @@ static struct command_result *age_layer(struct command *cmd, struct payment *pay
29703008 return send_outreq (req );
29713009}
29723010
2973- static struct command_result * xpay_layer_created (struct command * aux_cmd ,
2974- const char * method ,
2975- const char * buf ,
2976- const jsmntok_t * result ,
2977- void * unused )
2978- {
2979- return aux_command_done (aux_cmd );
2980- }
2981-
29823011static struct command_result * json_xkeysend (struct command * cmd ,
29833012 const char * buf ,
29843013 const jsmntok_t * params )
@@ -3009,6 +3038,8 @@ static struct command_result *json_xkeysend(struct command *cmd,
30093038 p_opt ("extratlvs" , param_extra_tlvs , & extra_fields ),
30103039 NULL ))
30113040 return command_param_failed ();
3041+ if (!xpay -> ready )
3042+ return command_fail (cmd , PLUGIN_ERROR , "xpay is initializing" );
30123043
30133044 randbytes (& preimage , sizeof (preimage ));
30143045 sha256 (& payment_hash , & preimage , sizeof (preimage ));
@@ -3102,20 +3133,6 @@ static const char *init(struct command *init_cmd,
31023133 json_add_u32 (req -> js , "last_height" , 0 );
31033134 send_outreq (req );
31043135
3105- req = jsonrpc_request_start (aux_command (init_cmd ), "getinfo" ,
3106- getinfo_done ,
3107- plugin_broken_cb ,
3108- "getinfo" );
3109- send_outreq (req );
3110-
3111- req = jsonrpc_request_start (aux_command (init_cmd ), "askrene-create-layer" ,
3112- xpay_layer_created ,
3113- plugin_broken_cb ,
3114- "askrene-create-layer" );
3115- json_add_string (req -> js , "layer" , "xpay" );
3116- json_add_bool (req -> js , "persistent" , true);
3117- send_outreq (req );
3118-
31193136 return NULL ;
31203137}
31213138
@@ -3410,6 +3427,7 @@ int main(int argc, char *argv[])
34103427 xpay -> slow_mode = false;
34113428 xpay -> dev_no_age = false;
34123429 xpay -> user_layers = tal_arr (xpay , const char * , 0 );
3430+ xpay -> ready = false;
34133431 list_head_init (& xpay -> payments );
34143432 plugin_main (argv , init , take (xpay ),
34153433 PLUGIN_RESTARTABLE , true, NULL ,
0 commit comments