@@ -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 )) {
@@ -2513,6 +2523,8 @@ static struct payment *new_payment(const tal_t *ctx,
25132523bool attempt_ongoing (struct plugin * plugin , const struct sha256 * payment_hash )
25142524{
25152525 struct xpay * xpay = xpay_of (plugin );
2526+ if (!xpay -> ready )
2527+ return false;
25162528 const struct payment * payment ;
25172529
25182530 list_for_each (& xpay -> payments , payment , list ) {
@@ -2815,6 +2827,7 @@ static struct command_result *json_sendamount(struct command *cmd,
28152827 const char * buffer ,
28162828 const jsmntok_t * params )
28172829{
2830+ struct xpay * xpay = xpay_of (cmd -> plugin );
28182831 struct amount_msat * send_msat , * maxfee ;
28192832 struct amount_msat invoice_msat ;
28202833 const char * invstring ;
@@ -2837,6 +2850,8 @@ static struct command_result *json_sendamount(struct command *cmd,
28372850 p_opt ("label" , param_label , & label ),
28382851 NULL ))
28392852 return command_param_failed ();
2853+ if (!xpay -> ready )
2854+ return command_fail (cmd , PLUGIN_ERROR , "xpay is initializing" );
28402855
28412856 // FIXME: why does xpay returns this only after
28422857 // preapproveinvoice_succeed?
@@ -2901,21 +2916,15 @@ static struct command_result *json_sendamount(struct command *cmd,
29012916 label , NULL , false, false, send_msat );
29022917}
29032918
2904- static struct command_result * getchaininfo_done (struct command * aux_cmd ,
2905- const char * method ,
2906- const char * buf ,
2907- const jsmntok_t * result ,
2908- void * unused )
2919+ static struct command_result * xpay_layer_created (struct command * aux_cmd ,
2920+ const char * method ,
2921+ const char * buf ,
2922+ const jsmntok_t * result ,
2923+ void * unused )
29092924{
29102925 struct xpay * xpay = xpay_of (aux_cmd -> plugin );
2911-
2912- /* We use headercount from the backend, in case we're still syncing */
2913- if (!json_to_u32 (buf , json_get_member (buf , result , "headercount" ),
2914- & xpay -> blockheight )) {
2915- plugin_err (aux_cmd -> plugin , "Bad getchaininfo '%.*s'" ,
2916- json_tok_full_len (result ),
2917- json_tok_full (buf , result ));
2918- }
2926+ xpay -> ready = true;
2927+ plugin_log (aux_cmd -> plugin , LOG_INFORM , "xpay is ready" );
29192928 return aux_command_done (aux_cmd );
29202929}
29212930
@@ -2927,6 +2936,7 @@ static struct command_result *getinfo_done(struct command *aux_cmd,
29272936{
29282937 struct xpay * xpay = xpay_of (aux_cmd -> plugin );
29292938 const char * err ;
2939+ struct out_req * req ;
29302940
29312941 err = json_scan (tmpctx , buf , result ,
29322942 "{id:%}" , JSON_SCAN (json_to_pubkey , & xpay -> local_id ));
@@ -2936,7 +2946,35 @@ static struct command_result *getinfo_done(struct command *aux_cmd,
29362946 json_tok_full (buf , result ),
29372947 err );
29382948 }
2939- return aux_command_done (aux_cmd );
2949+
2950+ req = jsonrpc_request_start (aux_cmd , "askrene-create-layer" ,
2951+ xpay_layer_created , plugin_broken_cb ,
2952+ "askrene-create-layer" );
2953+ json_add_string (req -> js , "layer" , "xpay" );
2954+ json_add_bool (req -> js , "persistent" , true);
2955+ return send_outreq (req );
2956+ }
2957+
2958+ static struct command_result * getchaininfo_done (struct command * aux_cmd ,
2959+ const char * method ,
2960+ const char * buf ,
2961+ const jsmntok_t * result ,
2962+ void * unused )
2963+ {
2964+ struct xpay * xpay = xpay_of (aux_cmd -> plugin );
2965+ struct out_req * req ;
2966+
2967+ /* We use headercount from the backend, in case we're still syncing */
2968+ if (!json_to_u32 (buf , json_get_member (buf , result , "headercount" ),
2969+ & xpay -> blockheight )) {
2970+ plugin_err (aux_cmd -> plugin , "Bad getchaininfo '%.*s'" ,
2971+ json_tok_full_len (result ),
2972+ json_tok_full (buf , result ));
2973+ }
2974+
2975+ req = jsonrpc_request_start (aux_cmd , "getinfo" , getinfo_done ,
2976+ plugin_broken_cb , "getinfo" );
2977+ return send_outreq (req );
29402978}
29412979
29422980static struct command_result * populate_private_layer (struct command * cmd ,
@@ -2968,15 +3006,6 @@ static struct command_result *age_layer(struct command *cmd, struct payment *pay
29683006 return send_outreq (req );
29693007}
29703008
2971- static struct command_result * xpay_layer_created (struct command * aux_cmd ,
2972- const char * method ,
2973- const char * buf ,
2974- const jsmntok_t * result ,
2975- void * unused )
2976- {
2977- return aux_command_done (aux_cmd );
2978- }
2979-
29803009static struct command_result * json_xkeysend (struct command * cmd ,
29813010 const char * buf ,
29823011 const jsmntok_t * params )
@@ -3007,6 +3036,8 @@ static struct command_result *json_xkeysend(struct command *cmd,
30073036 p_opt ("extratlvs" , param_extra_tlvs , & extra_fields ),
30083037 NULL ))
30093038 return command_param_failed ();
3039+ if (!xpay -> ready )
3040+ return command_fail (cmd , PLUGIN_ERROR , "xpay is initializing" );
30103041
30113042 randbytes (& preimage , sizeof (preimage ));
30123043 sha256 (& payment_hash , & preimage , sizeof (preimage ));
@@ -3100,20 +3131,6 @@ static const char *init(struct command *init_cmd,
31003131 json_add_u32 (req -> js , "last_height" , 0 );
31013132 send_outreq (req );
31023133
3103- req = jsonrpc_request_start (aux_command (init_cmd ), "getinfo" ,
3104- getinfo_done ,
3105- plugin_broken_cb ,
3106- "getinfo" );
3107- send_outreq (req );
3108-
3109- req = jsonrpc_request_start (aux_command (init_cmd ), "askrene-create-layer" ,
3110- xpay_layer_created ,
3111- plugin_broken_cb ,
3112- "askrene-create-layer" );
3113- json_add_string (req -> js , "layer" , "xpay" );
3114- json_add_bool (req -> js , "persistent" , true);
3115- send_outreq (req );
3116-
31173134 return NULL ;
31183135}
31193136
@@ -3408,6 +3425,7 @@ int main(int argc, char *argv[])
34083425 xpay -> slow_mode = false;
34093426 xpay -> dev_no_age = false;
34103427 xpay -> user_layers = tal_arr (xpay , const char * , 0 );
3428+ xpay -> ready = false;
34113429 list_head_init (& xpay -> payments );
34123430 plugin_main (argv , init , take (xpay ),
34133431 PLUGIN_RESTARTABLE , true, NULL ,
0 commit comments