diff --git a/plugins/renepay/pay.c b/plugins/renepay/pay.c index a13e7c19d..c91c96327 100644 --- a/plugins/renepay/pay.c +++ b/plugins/renepay/pay.c @@ -32,9 +32,9 @@ static struct pay_plugin the_pay_plugin; struct pay_plugin * const pay_plugin = &the_pay_plugin; -static void timer_kick(struct renepay * renepay); +static void timer_kick(struct payment *payment); static struct command_result *try_paying(struct command *cmd, - struct renepay * renepay, + struct payment *payment, bool first_time); void amount_msat_accumulate_(struct amount_msat *dst, @@ -126,56 +126,54 @@ static const char *init(struct plugin *p, } -static void renepay_settimer(struct renepay * renepay) +static void payment_settimer(struct payment *payment) { - renepay->rexmit_timer = tal_free(renepay->rexmit_timer); - renepay->rexmit_timer = plugin_timer( + payment->rexmit_timer = tal_free(payment->rexmit_timer); + payment->rexmit_timer = plugin_timer( pay_plugin->plugin, time_from_msec(TIMER_COLLECT_FAILURES_MSEC), - timer_kick, renepay); + timer_kick, payment); } /* Happens when timer goes off, but also works to arm timer if nothing to do */ -static void timer_kick(struct renepay * renepay) +static void timer_kick(struct payment *payment) { - struct payment * const p = renepay->payment; plugin_log(pay_plugin->plugin,LOG_DBG,"calling %s",__PRETTY_FUNCTION__); - switch(p->status) + switch (payment->status) { /* Some flows succeeded, we finish the payment. */ case PAYMENT_SUCCESS: plugin_log(pay_plugin->plugin,LOG_DBG,"status is PAYMENT_SUCCESS"); - renepay_success(renepay); + payment_success(payment); break; /* Some flows failed, we retry. */ case PAYMENT_FAIL: plugin_log(pay_plugin->plugin,LOG_DBG,"status is PAYMENT_FAIL"); - payment_assert_delivering_incomplete(p); - try_paying(renepay->cmd,renepay,/* always try even if prob is low */ true); + payment_assert_delivering_incomplete(payment); + try_paying(payment->cmd,payment,/* always try even if prob is low */ true); break; /* Nothing has returned yet, we have to wait. */ case PAYMENT_PENDING: plugin_log(pay_plugin->plugin,LOG_DBG,"status is PAYMENT_PENDING"); - payment_assert_delivering_all(p); - renepay_settimer(renepay); + payment_assert_delivering_all(payment); + payment_settimer(payment); break; } } /* Sometimes we don't know exactly who to blame... */ -static struct command_result *handle_unhandleable_error(struct renepay * renepay, +static struct command_result *handle_unhandleable_error(struct payment *payment, struct pay_flow *flow, const char *what) { - struct payment * const p = renepay->payment; plugin_log(pay_plugin->plugin,LOG_DBG,"calling %s",__PRETTY_FUNCTION__); size_t n = tal_count(flow); /* We got a mangled reply. We don't know who to penalize! */ - debug_paynote(p, "%s on route %s", what, flow_path_to_str(tmpctx, flow)); + debug_paynote(payment, "%s on route %s", what, flow_path_to_str(tmpctx, flow)); // TODO(eduardo): does LOG_BROKEN finish the plugin execution? plugin_log(pay_plugin->plugin, LOG_BROKEN, @@ -185,7 +183,7 @@ static struct command_result *handle_unhandleable_error(struct renepay * renepay if (n == 1) { payflow_fail(flow); - return renepay_fail(renepay, PAY_UNPARSEABLE_ONION, + return payment_fail(payment, PAY_UNPARSEABLE_ONION, "Got %s from the destination", what); } /* FIXME: check chan_extra_map, since we might have succeeded though @@ -199,8 +197,8 @@ static struct command_result *handle_unhandleable_error(struct renepay * renepay /* Assume it's not the destination */ n = pseudorand(n-1); - tal_arr_expand(&renepay->disabled, flow->path_scids[n]); - debug_paynote(p, "... eliminated %s", + tal_arr_expand(&payment->disabled, flow->path_scids[n]); + debug_paynote(payment, "... eliminated %s", type_to_string(tmpctx, struct short_channel_id, &flow->path_scids[n])); return NULL; @@ -219,13 +217,13 @@ static struct command_result *addgossip_done(struct command *cmd, struct addgossip *adg) { plugin_log(pay_plugin->plugin,LOG_DBG,"calling %s",__PRETTY_FUNCTION__); - struct renepay * renepay = adg->flow->payment->renepay; + struct payment * payment = adg->flow->payment; /* Release this: if it's the last flow we'll retry immediately */ payflow_fail(adg->flow); tal_free(adg); - renepay_settimer(renepay); + payment_settimer(payment); return command_still_pending(cmd); } @@ -236,14 +234,13 @@ static struct command_result *addgossip_failure(struct command *cmd, struct addgossip *adg) { + struct payment * payment = adg->flow->payment; plugin_log(pay_plugin->plugin,LOG_DBG,"calling %s",__PRETTY_FUNCTION__); - struct payment * p = adg->flow->payment; - struct renepay * renepay = p->renepay; - debug_paynote(p, "addgossip failed, removing channel %s (%.*s)", + debug_paynote(payment, "addgossip failed, removing channel %s (%.*s)", type_to_string(tmpctx, struct short_channel_id, &adg->scid), err->end - err->start, buf + err->start); - tal_arr_expand(&renepay->disabled, adg->scid); + tal_arr_expand(&payment->disabled, adg->scid); return addgossip_done(cmd, buf, err, adg); } @@ -254,8 +251,7 @@ static struct command_result *submit_update(struct command *cmd, struct short_channel_id errscid) { plugin_log(pay_plugin->plugin,LOG_DBG,"calling %s",__PRETTY_FUNCTION__); - struct payment * p = flow->payment; - struct renepay * renepay = p->renepay; + struct payment *payment = flow->payment; struct out_req *req; struct addgossip *adg = tal(cmd, struct addgossip); @@ -264,10 +260,9 @@ static struct command_result *submit_update(struct command *cmd, adg->scid = errscid; adg->flow = flow; /* Disable re-xmit until this returns */ - renepay->rexmit_timer - = tal_free(renepay->rexmit_timer); + payment->rexmit_timer = tal_free(payment->rexmit_timer); - debug_paynote(p, "... extracted channel_update, telling gossipd"); + debug_paynote(payment, "... extracted channel_update, telling gossipd"); plugin_log(pay_plugin->plugin, LOG_DBG, "(update = %s)", tal_hex(tmpctx, update)); req = jsonrpc_request_start(pay_plugin->plugin, NULL, "addgossip", @@ -357,13 +352,12 @@ static struct command_result *flow_sendpay_failed(struct command *cmd, { plugin_log(pay_plugin->plugin,LOG_DBG,"calling %s",__PRETTY_FUNCTION__); - struct payment *p = flow->payment; - debug_assert(p); - struct renepay * renepay = p->renepay; - debug_assert(renepay); + struct payment *payment = flow->payment; + debug_assert(payment); /* This is a fail. */ - payment_fail(p); + if (payment->status != PAYMENT_SUCCESS) + payment->status=PAYMENT_FAIL; u64 errcode; const jsmntok_t *msg = json_get_member(buf, err, "message"); @@ -376,13 +370,13 @@ static struct command_result *flow_sendpay_failed(struct command *cmd, plugin_err(cmd->plugin, "Strange error from sendpay: %.*s", json_tok_full_len(err), json_tok_full(buf, err)); - debug_paynote(p, + debug_paynote(payment, "sendpay didn't like first hop, eliminated: %.*s", msg->end - msg->start, buf + msg->start); /* There is no new knowledge from this kind of failure. * We just disable this scid. */ - tal_arr_expand(&renepay->disabled, flow->path_scids[0]); + tal_arr_expand(&payment->disabled, flow->path_scids[0]); payflow_fail(flow); return command_still_pending(cmd); @@ -391,11 +385,9 @@ static struct command_result *flow_sendpay_failed(struct command *cmd, static struct command_result * sendpay_flows(struct command *cmd, - struct renepay * renepay, + struct payment *p, struct pay_flow **flows STEALS) { - struct payment * const p = renepay->payment; - plugin_log(pay_plugin->plugin,LOG_DBG,"calling %s",__PRETTY_FUNCTION__); debug_paynote(p, "Sending out batch of %zu payments", tal_count(flows)); @@ -476,44 +468,43 @@ sendpay_flows(struct command *cmd, tal_free(flows); /* Get ready to process replies */ - renepay_settimer(renepay); + payment_settimer(p); return command_still_pending(cmd); } static struct command_result *try_paying(struct command *cmd, - struct renepay *renepay, + struct payment *payment, bool first_time) { - struct payment * const p = renepay->payment; plugin_log(pay_plugin->plugin,LOG_DBG,"calling %s",__PRETTY_FUNCTION__); struct amount_msat feebudget, fees_spent, remaining; - renepay->payment->status=PAYMENT_PENDING; - if (time_after(time_now(), p->stop_time)) - return renepay_fail(renepay, PAY_STOPPED_RETRYING, "Timed out"); + payment->status = PAYMENT_PENDING; + if (time_after(time_now(), payment->stop_time)) + return payment_fail(payment, PAY_STOPPED_RETRYING, "Timed out"); /* Total feebudget */ - if (!amount_msat_sub(&feebudget, p->maxspend, p->amount)) + if (!amount_msat_sub(&feebudget, payment->maxspend, payment->amount)) { plugin_err(pay_plugin->plugin, "%s (line %d) could not substract maxspend=%s and amount=%s.", __PRETTY_FUNCTION__, __LINE__, - type_to_string(tmpctx, struct amount_msat, &p->maxspend), - type_to_string(tmpctx, struct amount_msat, &p->amount)); + type_to_string(tmpctx, struct amount_msat, &payment->maxspend), + type_to_string(tmpctx, struct amount_msat, &payment->amount)); } /* Fees spent so far */ - if (!amount_msat_sub(&fees_spent, p->total_sent, p->total_delivering)) + if (!amount_msat_sub(&fees_spent, payment->total_sent, payment->total_delivering)) { plugin_err(pay_plugin->plugin, "%s (line %d) could not substract total_sent=%s and total_delivering=%s.", __PRETTY_FUNCTION__, __LINE__, - type_to_string(tmpctx, struct amount_msat, &p->total_sent), - type_to_string(tmpctx, struct amount_msat, &p->total_delivering)); + type_to_string(tmpctx, struct amount_msat, &payment->total_sent), + type_to_string(tmpctx, struct amount_msat, &payment->total_delivering)); } /* Remaining fee budget. */ @@ -528,14 +519,14 @@ static struct command_result *try_paying(struct command *cmd, } /* How much are we still trying to send? */ - if (!amount_msat_sub(&remaining, p->amount, p->total_delivering)) + if (!amount_msat_sub(&remaining, payment->amount, payment->total_delivering)) { plugin_err(pay_plugin->plugin, "%s (line %d) could not substract amount=%s and total_delivering=%s.", __PRETTY_FUNCTION__, __LINE__, - type_to_string(tmpctx, struct amount_msat, &p->amount), - type_to_string(tmpctx, struct amount_msat, &p->total_delivering)); + type_to_string(tmpctx, struct amount_msat, &payment->amount), + type_to_string(tmpctx, struct amount_msat, &payment->total_delivering)); } // plugin_log(pay_plugin->plugin,LOG_DBG,fmt_chan_extra_map(tmpctx,pay_plugin->chan_extra_map)); @@ -544,9 +535,9 @@ static struct command_result *try_paying(struct command *cmd, /* We let this return an unlikely path, as it's better to try once * than simply refuse. Plus, models are not truth! */ - gossmap_apply_localmods(pay_plugin->gossmap, renepay->local_gossmods); + gossmap_apply_localmods(pay_plugin->gossmap, payment->local_gossmods); struct pay_flow **pay_flows = get_payflows( - renepay, + payment, remaining, feebudget, /* would you accept unlikely @@ -554,46 +545,59 @@ static struct command_result *try_paying(struct command *cmd, true, /* is entire payment? */ - amount_msat_eq(p->total_delivering, AMOUNT_MSAT(0)), + amount_msat_eq(payment->total_delivering, AMOUNT_MSAT(0)), &err_msg); - gossmap_remove_localmods(pay_plugin->gossmap, renepay->local_gossmods); + gossmap_remove_localmods(pay_plugin->gossmap, payment->local_gossmods); // plugin_log(pay_plugin->plugin,LOG_DBG,"get_payflows produced %s",fmt_payflows(tmpctx,pay_flows)); /* MCF cannot find a feasible route, we stop. */ if (!pay_flows) { - return renepay_fail(renepay, PAY_ROUTE_NOT_FOUND, + return payment_fail(payment, PAY_ROUTE_NOT_FOUND, "Failed to find a route, %s", err_msg); } /* Now begin making payments */ - return sendpay_flows(cmd, renepay, pay_flows); + return sendpay_flows(cmd, payment, pay_flows); +} + +static void destroy_cmd_payment_ptr(struct command *cmd, + struct payment *payment) +{ + assert(payment->cmd == cmd); + payment->cmd = NULL; } static struct command_result *listpeerchannels_done( struct command *cmd, const char *buf, const jsmntok_t *result, - struct renepay *renepay) + struct payment *payment) { plugin_log(pay_plugin->plugin,LOG_DBG,"calling %s",__PRETTY_FUNCTION__); if (!uncertainty_network_update_from_listpeerchannels( pay_plugin->chan_extra_map, pay_plugin->my_id, - renepay, + payment, buf, result)) - return renepay_fail(renepay,LIGHTNINGD, + return command_fail(cmd, LIGHTNINGD, "listpeerchannels malformed: %.*s", json_tok_full_len(result), json_tok_full(buf, result)); // TODO(eduardo): check that there won't be a prob. cost associated with // any gossmap local chan. The same way there aren't fees to pay for my // local channels. - return try_paying(cmd, renepay, true); + + /* From now on, we keep a record of the payment, so persist it beyond this cmd. */ + tal_steal(pay_plugin->plugin, payment); + /* When we terminate cmd for any reason, clear it from payment so we don't do it again. */ + tal_add_destructor2(cmd, destroy_cmd_payment_ptr, payment); + + return try_paying(cmd, payment, true); } @@ -685,10 +689,9 @@ payment_listsendpays_previous( struct command *cmd, const char *buf, const jsmntok_t *result, - struct renepay * renepay) + struct payment * payment) { debug_info("calling %s",__PRETTY_FUNCTION__); - struct payment * p = renepay->payment; size_t i; const jsmntok_t *t, *arr, *err; @@ -841,25 +844,23 @@ payment_listsendpays_previous( json_add_string(ret, "status", "complete"); json_add_amount_msat(ret, "amount_msat", complete_msat); json_add_amount_msat(ret, "amount_sent_msat",complete_sent); - json_add_node_id(ret, "destination", &p->destination); - json_add_sha256(ret, "payment_hash", &p->payment_hash); + json_add_node_id(ret, "destination", &payment->destination); + json_add_sha256(ret, "payment_hash", &payment->payment_hash); json_add_u32(ret, "created_at", complete_created_at); json_add_num(ret, "parts", complete_parts); /* This payment was already completed, we don't keep record of - * it twice. */ - renepay->payment = tal_free(renepay->payment); - + * it twice: payment will be freed with cmd */ return command_finished(cmd, ret); } else if (pending) { assert(last_pending_group_id!=INVALID_ID); assert(first_pending_group_id!=INVALID_ID); - p->groupid = last_pending_group_id; - renepay->next_partid = last_pending_partid+1; + payment->groupid = last_pending_group_id; + payment->next_partid = last_pending_partid+1; - p->total_sent = pending_sent; - p->total_delivering = pending_msat; + payment->total_sent = pending_sent; + payment->total_delivering = pending_msat; plugin_log(pay_plugin->plugin,LOG_DBG, "There are pending sendpays to this invoice. " @@ -867,31 +868,29 @@ payment_listsendpays_previous( "delivering = %s, " "last_partid = %"PRIu64, last_pending_group_id, - type_to_string(tmpctx,struct amount_msat,&p->total_delivering), + type_to_string(tmpctx,struct amount_msat,&payment->total_delivering), last_pending_partid); if( first_pending_group_id != last_pending_group_id) { /* At least two pending groups for the same invoice, * this is weird, we better stop. */ - renepay->payment = tal_free(renepay->payment); - return renepay_fail(renepay, PAY_IN_PROGRESS, + return command_fail(cmd, PAY_IN_PROGRESS, "Payment is pending by some other request."); } - if(amount_msat_greater_eq(p->total_delivering,p->amount)) + if(amount_msat_greater_eq(payment->total_delivering,payment->amount)) { /* Pending payment already pays the full amount, we * better stop. */ - renepay->payment = tal_free(renepay->payment); - return renepay_fail(renepay, PAY_IN_PROGRESS, + return command_fail(cmd, PAY_IN_PROGRESS, "Payment is pending with full amount already commited"); } }else { /* There are no pending nor completed sendpays, get me the last * sendpay group. */ - p->groupid = (last_group==INVALID_ID ? 1 : (last_group+1)) ; - renepay->next_partid=1; + payment->groupid = (last_group==INVALID_ID ? 1 : (last_group+1)) ; + payment->next_partid=1; } @@ -899,7 +898,7 @@ payment_listsendpays_previous( /* Get local capacities... */ req = jsonrpc_request_start(cmd->plugin, cmd, "listpeerchannels", listpeerchannels_done, - listpeerchannels_done, renepay); + listpeerchannels_done, payment); return send_outreq(cmd->plugin, req); } @@ -1117,9 +1116,12 @@ static struct command_result *json_pay(struct command *cmd, *use_shadow = 1; #endif - /* renepay is bound to the command, if the command finishes renepay is - * freed. */ - struct renepay * renepay = renepay_new(cmd, + /* Payment is allocated off cmd to start, in case we fail cmd + * (e.g. already in progress, already succeeded). Once it's + * actually started, it persists beyond the command, so we + * tal_steal. */ + struct payment *payment = payment_new(cmd, + cmd, take(invstr), take(label), take(description), @@ -1138,14 +1140,10 @@ static struct command_result *json_pay(struct command *cmd, *riskfactor_millionths, *min_prob_success_millionths, use_shadow); - tal_add_destructor2(renepay, - renepay_cleanup, - pay_plugin->gossmap); - /* We inmediately add this payment to the payment list. */ - tal_steal(pay_plugin->ctx, renepay->payment); - list_add_tail(&pay_plugin->payments, &renepay->payment->list); - tal_add_destructor(renepay->payment, destroy_payment); + /* We immediately add this payment to the payment list. */ + list_add_tail(&pay_plugin->payments, &payment->list); + tal_add_destructor(payment, destroy_payment); plugin_log(pay_plugin->plugin,LOG_DBG,"Starting renepay"); bool gossmap_changed = gossmap_refresh(pay_plugin->gossmap, NULL); @@ -1191,7 +1189,7 @@ static struct command_result *json_pay(struct command *cmd, // TODO(eduardo): are there route hints for B12? // Add any extra hidden channel revealed by the routehints to the uncertainty network. if(invstr_is_b11) - uncertainty_network_add_routehints(pay_plugin->chan_extra_map,renepay); + uncertainty_network_add_routehints(pay_plugin->chan_extra_map, payment); if(!uncertainty_network_check_invariants(pay_plugin->chan_extra_map)) plugin_log(pay_plugin->plugin, @@ -1203,9 +1201,9 @@ static struct command_result *json_pay(struct command *cmd, struct out_req *req = jsonrpc_request_start(cmd->plugin, cmd, "listsendpays", payment_listsendpays_previous, - payment_listsendpays_previous, renepay); + payment_listsendpays_previous, payment); - json_add_sha256(req->js, "payment_hash", &renepay->payment->payment_hash); + json_add_sha256(req->js, "payment_hash", &payment->payment_hash); return send_outreq(cmd->plugin, req); } @@ -1213,12 +1211,10 @@ static void handle_sendpay_failure_renepay( struct command *cmd, const char *buf, const jsmntok_t *result, - struct renepay *renepay, + struct payment *p, struct pay_flow *flow) { - debug_assert(renepay); debug_assert(flow); - struct payment *p = renepay->payment; debug_assert(p); u64 errcode; @@ -1249,11 +1245,11 @@ static void handle_sendpay_failure_renepay( case PAY_TRY_OTHER_ROUTE: break; case PAY_DESTINATION_PERM_FAIL: - renepay_fail(renepay,errcode, + payment_fail(p, errcode, "Got a final failure from destination"); return; default: - renepay_fail(renepay,errcode, + payment_fail(p, errcode, "Unexpected errocode from sendpay_failure: %.*s", json_tok_full_len(result), json_tok_full(buf,result)); @@ -1315,7 +1311,7 @@ static void handle_sendpay_failure_renepay( { // TODO(eduardo): I wonder which error code should I show the // user in this case? - renepay_fail(renepay,LIGHTNINGD, + payment_fail(p,LIGHTNINGD, "Failed to get failcode from sendpay_failure notification" ", received json: %.*s", json_tok_full_len(result), @@ -1355,7 +1351,7 @@ static void handle_sendpay_failure_renepay( case WIRE_EXPIRY_TOO_FAR: debug_paynote(p, "we're removing scid %s", type_to_string(tmpctx,struct short_channel_id,&errscid)); - tal_arr_expand(&renepay->disabled, errscid); + tal_arr_expand(&p->disabled, errscid); return; /* These can be fixed (maybe) by applying the included channel_update */ @@ -1375,7 +1371,7 @@ static void handle_sendpay_failure_renepay( debug_paynote(p, "missing an update, so we're removing scid %s", type_to_string(tmpctx,struct short_channel_id,&errscid)); - tal_arr_expand(&renepay->disabled, errscid); + tal_arr_expand(&p->disabled, errscid); return; case WIRE_TEMPORARY_CHANNEL_FAILURE: @@ -1387,7 +1383,7 @@ static void handle_sendpay_failure_renepay( case WIRE_FINAL_INCORRECT_CLTV_EXPIRY: case WIRE_FINAL_INCORRECT_HTLC_AMOUNT: debug_paynote(p,"final destination failure"); - renepay_fail(renepay,errcode, + payment_fail(p,errcode, "Destination said %s: %s", onion_wire_name(onionerr), message); @@ -1400,7 +1396,7 @@ static void handle_sendpay_failure_renepay( { debug_paynote(p,"unkown onion error code %u, fatal", onionerr); - renepay_fail(renepay,errcode, + payment_fail(p,errcode, "Destination gave unknown error code %u: %s", onionerr,message); return; @@ -1409,12 +1405,12 @@ static void handle_sendpay_failure_renepay( debug_paynote(p,"unkown onion error code %u, removing scid %s", onionerr, type_to_string(tmpctx,struct short_channel_id,&errscid)); - tal_arr_expand(&renepay->disabled, errscid); + tal_arr_expand(&p->disabled, errscid); return; } unhandleable: // TODO(eduardo): check - handle_unhandleable_error(renepay, flow, ""); + handle_unhandleable_error(p, flow, ""); } static void handle_sendpay_failure_flow( @@ -1428,7 +1424,8 @@ static void handle_sendpay_failure_flow( debug_assert(flow); struct payment * const p = flow->payment; - payment_fail(p); + if (p->status != PAYMENT_SUCCESS) + p->status=PAYMENT_FAIL; u64 errcode; if (!json_to_u64(buf, json_get_member(buf, result, "code"), &errcode)) @@ -1620,8 +1617,7 @@ static struct command_result *notification_sendpay_success( // 3. mark as success struct payment * const p = flow->payment; debug_assert(p); - - payment_success(p); + p->status = PAYMENT_SUCCESS; const jsmntok_t *preimagetok = json_get_member(buf, resulttok, "payment_preimage"); @@ -1633,6 +1629,8 @@ static struct command_result *notification_sendpay_success( json_tok_full_len(params), json_tok_full(buf,params)); + /* We could have preimage from previous part */ + tal_free(p->preimage); p->preimage = tal_dup_or_null(p,struct preimage,&preimage); // 4. update information and release pending HTLCs @@ -1706,10 +1704,7 @@ static struct command_result *notification_sendpay_failure( handle_sendpay_failure_flow(cmd,buf,resulttok,flow); // there is possibly a pending renepay command for this flow - struct renepay * const renepay = flow->payment->renepay; - - if(renepay) - handle_sendpay_failure_renepay(cmd,buf,resulttok,renepay,flow); + handle_sendpay_failure_renepay(cmd,buf,resulttok,flow->payment,flow); done: if(flow) payflow_fail(flow); diff --git a/plugins/renepay/pay_flow.c b/plugins/renepay/pay_flow.c index 91c691ab4..0776dc326 100644 --- a/plugins/renepay/pay_flow.c +++ b/plugins/renepay/pay_flow.c @@ -137,11 +137,10 @@ static u64 flow_delay(const struct flow *flow) /* This enhances f->amounts, and returns per-flow cltvs */ static u32 *shadow_additions(const tal_t *ctx, const struct gossmap *gossmap, - struct renepay *renepay, + struct payment *p, struct flow **flows, bool is_entire_payment) { - struct payment * p = renepay->payment; u32 *final_cltvs; /* Set these up now in case we decide to do nothing */ @@ -279,12 +278,11 @@ static u64 flows_worst_delay(struct flow **flows) } /* FIXME: If only path has channels marked disabled, we should try... */ -static bool disable_htlc_violations_oneflow(struct renepay * renepay, +static bool disable_htlc_violations_oneflow(struct payment *p, const struct flow *flow, const struct gossmap *gossmap, bitmap *disabled) { - struct payment * p = renepay->payment; bool disabled_some = false; for (size_t i = 0; i < tal_count(flow->path); i++) { @@ -307,7 +305,7 @@ static bool disable_htlc_violations_oneflow(struct renepay * renepay, reason); /* Add this for future searches for this payment. */ - tal_arr_expand(&renepay->disabled, scid); + tal_arr_expand(&p->disabled, scid); /* Add to existing bitmap */ bitmap_set_bit(disabled, gossmap_chan_idx(gossmap, flow->path[i])); @@ -318,7 +316,7 @@ static bool disable_htlc_violations_oneflow(struct renepay * renepay, /* If we can't use one of these flows because we hit limits, we disable that * channel for future searches and return false */ -static bool disable_htlc_violations(struct renepay *renepay, +static bool disable_htlc_violations(struct payment *payment, struct flow **flows, const struct gossmap *gossmap, bitmap *disabled) @@ -327,7 +325,7 @@ static bool disable_htlc_violations(struct renepay *renepay, /* We continue through all of them, to disable many at once. */ for (size_t i = 0; i < tal_count(flows); i++) { - disabled_some |= disable_htlc_violations_oneflow(renepay, flows[i], + disabled_some |= disable_htlc_violations_oneflow(payment, flows[i], gossmap, disabled); } @@ -335,7 +333,7 @@ static bool disable_htlc_violations(struct renepay *renepay, } /* Get some payment flows to get this amount to destination, or NULL. */ -struct pay_flow **get_payflows(struct renepay * renepay, +struct pay_flow **get_payflows(struct payment *p, struct amount_msat amount, struct amount_msat feebudget, bool unlikely_ok, @@ -344,12 +342,11 @@ struct pay_flow **get_payflows(struct renepay * renepay, { *err_msg = tal_fmt(tmpctx,"[no error]"); - struct payment * p = renepay->payment; bitmap *disabled; struct pay_flow **pay_flows; const struct gossmap_node *src, *dst; - disabled = make_disabled_bitmap(tmpctx, pay_plugin->gossmap, renepay->disabled); + disabled = make_disabled_bitmap(tmpctx, pay_plugin->gossmap, p->disabled); src = gossmap_find_node(pay_plugin->gossmap, &pay_plugin->my_id); if (!src) { debug_paynote(p, "We don't have any channels?"); @@ -453,7 +450,7 @@ struct pay_flow **get_payflows(struct renepay * renepay, * to do this inside minflow(), but the diagnostics here * are far better, since we can report min/max which * *actually* made us reconsider. */ - if (disable_htlc_violations(renepay, flows, pay_plugin->gossmap, + if (disable_htlc_violations(p, flows, pay_plugin->gossmap, disabled)) { continue; // retry @@ -462,12 +459,12 @@ struct pay_flow **get_payflows(struct renepay * renepay, /* This can adjust amounts and final cltv for each flow, * to make it look like it's going elsewhere */ final_cltvs = shadow_additions(tmpctx, pay_plugin->gossmap, - renepay, flows, is_entire_payment); + p, flows, is_entire_payment); /* OK, we are happy with these flows: convert to * pay_flows to outlive the current gossmap. */ - pay_flows = flows_to_pay_flows(renepay->payment, pay_plugin->gossmap, + pay_flows = flows_to_pay_flows(p, pay_plugin->gossmap, flows, final_cltvs, - &renepay->next_partid); + &p->next_partid); break; } @@ -628,7 +625,8 @@ struct pay_flow* payflow_fail(struct pay_flow *flow) struct payment * p = flow->payment; debug_assert(p); - payment_fail(p); + if (p->status != PAYMENT_SUCCESS) + p->status = PAYMENT_FAIL; amount_msat_reduce(&p->total_delivering, payflow_delivered(flow)); amount_msat_reduce(&p->total_sent, flow->amounts[0]); diff --git a/plugins/renepay/pay_flow.h b/plugins/renepay/pay_flow.h index 1a6e9b73c..bda8564e0 100644 --- a/plugins/renepay/pay_flow.h +++ b/plugins/renepay/pay_flow.h @@ -78,7 +78,7 @@ HTABLE_DEFINE_TYPE(struct pay_flow, payflow_map); -struct pay_flow **get_payflows(struct renepay * renepay, +struct pay_flow **get_payflows(struct payment *payment, struct amount_msat amount, struct amount_msat feebudget, bool unlikely_ok, diff --git a/plugins/renepay/payment.c b/plugins/renepay/payment.c index b9baf5792..5216b808c 100644 --- a/plugins/renepay/payment.c +++ b/plugins/renepay/payment.c @@ -3,7 +3,8 @@ #include #include -static struct payment * payment_new(struct renepay * renepay, +struct payment *payment_new(const tal_t *ctx, + struct command *cmd, const char *invstr TAKES, const char *label TAKES, const char *description TAKES, @@ -24,8 +25,8 @@ static struct payment * payment_new(struct renepay * renepay, u64 min_prob_success_millionths, bool use_shadow) { - struct payment *p = tal(renepay,struct payment); - p->renepay = renepay; + struct payment *p = tal(ctx,struct payment); + p->cmd = cmd; p->paynotes = tal_arr(p, const char *, 0); p->total_sent = AMOUNT_MSAT(0); @@ -61,66 +62,14 @@ static struct payment * payment_new(struct renepay * renepay, p->groupid=1; p->result = NULL; + p->local_gossmods = gossmap_localmods_new(p); + p->disabled = tal_arr(p,struct short_channel_id,0); + p->rexmit_timer = NULL; + p->next_partid=1; + return p; } -struct renepay *renepay_new(struct command *cmd, - const char *invstr TAKES, - const char *label TAKES, - const char *description TAKES, - const struct sha256 *local_offer_id TAKES, - const struct secret *payment_secret TAKES, - const u8 *payment_metadata TAKES, - const struct node_id *destination, - const struct sha256 *payment_hash, - struct amount_msat amount, - struct amount_msat maxfee, - unsigned int maxdelay, - u64 retryfor, - u16 final_cltv, - /* Tweakable in DEVELOPER mode */ - u64 base_fee_penalty, - u64 prob_cost_factor, - u64 riskfactor_millionths, - u64 min_prob_success_millionths, - bool use_shadow) -{ - struct renepay *renepay = tal(cmd,struct renepay); - - renepay->cmd = cmd; - renepay->payment = payment_new(renepay, - invstr, label, description, - local_offer_id, payment_secret, payment_metadata, - destination, payment_hash, - amount, maxfee, maxdelay, - retryfor, final_cltv, - base_fee_penalty, - prob_cost_factor, - riskfactor_millionths, - min_prob_success_millionths, - use_shadow); - - renepay->local_gossmods = gossmap_localmods_new(renepay); - renepay->disabled = tal_arr(renepay,struct short_channel_id,0); - renepay->rexmit_timer = NULL; - renepay->next_partid=1; - - return renepay; -} - - -void payment_fail(struct payment * p) -{ - /* If the payment already succeeded this function call must correspond - * to an old sendpay. */ - if(p->status == PAYMENT_SUCCESS)return; - p->status=PAYMENT_FAIL; -} -void payment_success(struct payment * p) -{ - p->status=PAYMENT_SUCCESS; -} - struct amount_msat payment_sent(const struct payment *p) { return p->total_sent; @@ -180,22 +129,25 @@ void payment_assert_delivering_all(const struct payment *p) } } -struct command_result *renepay_success(struct renepay * renepay) +struct command_result *payment_success(struct payment *p) { debug_info("calling %s",__PRETTY_FUNCTION__); - struct payment *p = renepay->payment; - payment_success(p); + p->status = PAYMENT_SUCCESS; payment_assert_delivering_all(p); + /* We only finish command once: its destructor clears this. */ + if (!p->cmd) + return NULL; + struct json_stream *response - = jsonrpc_stream_success(renepay->cmd); + = jsonrpc_stream_success(p->cmd); /* Any one succeeding is success. */ json_add_preimage(response, "payment_preimage", p->preimage); json_add_sha256(response, "payment_hash", &p->payment_hash); json_add_timeabs(response, "created_at", p->start_time); - json_add_u32(response, "parts", renepay_parts(renepay)); + json_add_u32(response, "parts", payment_parts(p)); json_add_amount_msat(response, "amount_msat", p->amount); json_add_amount_msat(response, "amount_sent_msat", @@ -203,51 +155,45 @@ struct command_result *renepay_success(struct renepay * renepay) json_add_string(response, "status", "complete"); json_add_node_id(response, "destination", &p->destination); - return command_finished(renepay->cmd, response); + return command_finished(p->cmd, response); } -struct command_result *renepay_fail( - struct renepay * renepay, +struct command_result *payment_fail( + struct payment *payment, enum jsonrpc_errcode code, const char *fmt, ...) { - /* renepay_fail is called after command finished. */ - if(renepay==NULL) - { - return command_still_pending(NULL); - } - payment_fail(renepay->payment); + /* We only finish command once: its destructor clears this. */ + if (!payment->cmd) + return NULL; + + if (payment->status != PAYMENT_SUCCESS) + payment->status = PAYMENT_FAIL; va_list args; va_start(args, fmt); char *message = tal_vfmt(tmpctx,fmt,args); va_end(args); - debug_paynote(renepay->payment,"%s",message); + debug_paynote(payment,"%s",message); - return command_fail(renepay->cmd,code,"%s",message); + return command_fail(payment->cmd,code,"%s",message); } -u64 renepay_parts(const struct renepay *renepay) +u64 payment_parts(const struct payment *payment) { - return renepay->next_partid-1; + return payment->next_partid-1; } /* Either the payment succeeded or failed, we need to cleanup/set the plugin * into a valid state before the next payment. */ -void renepay_cleanup( - struct renepay * renepay, - struct gossmap * gossmap) +void payment_cleanup(struct payment *payment) { debug_info("calling %s",__PRETTY_FUNCTION__); // TODO(eduardo): it can happen that local_gossmods removed below // contained a set of channels for which there is information in the // uncertainty network (chan_extra_map) and that are part of some pending // payflow (payflow_map). Handle this situation. - tal_free(renepay->local_gossmods); - - renepay->rexmit_timer = tal_free(renepay->rexmit_timer); - - if(renepay->payment) - renepay->payment->renepay = NULL; + payment->local_gossmods = tal_free(payment->local_gossmods); + payment->rexmit_timer = tal_free(payment->rexmit_timer); } diff --git a/plugins/renepay/payment.h b/plugins/renepay/payment.h index 159028369..80c52d907 100644 --- a/plugins/renepay/payment.h +++ b/plugins/renepay/payment.h @@ -13,7 +13,20 @@ struct payment { /* Inside pay_plugin->payments list */ struct list_node list; - struct renepay * renepay; + /* The command if still running (needed for timer func) */ + struct command *cmd; + + /* Localmods to apply to gossip_map for our own use. */ + struct gossmap_localmods *local_gossmods; + + /* Channels we decided to disable for various reasons. */ + struct short_channel_id *disabled; + + /* Timers. */ + struct plugin_timer *rexmit_timer; + + /* Used in get_payflows to set ids to each pay_flow. */ + u64 next_partid; /* Chatty description of attempts. */ const char **paynotes; @@ -32,7 +45,6 @@ struct payment { struct node_id destination; struct sha256 payment_hash; - /* Limits on what routes we'll accept. */ struct amount_msat maxspend; @@ -100,30 +112,9 @@ struct payment { struct command_result * result; }; -/* Data only kept while the payment is being processed. */ -struct renepay -{ - /* The command, and our owner (needed for timer func) */ - struct command *cmd; - /* Payment information that will eventually outlive renepay and be - * registered. */ - struct payment * payment; - - /* Localmods to apply to gossip_map for our own use. */ - struct gossmap_localmods *local_gossmods; - - /* Channels we decided to disable for various reasons. */ - struct short_channel_id *disabled; - - /* Timers. */ - struct plugin_timer *rexmit_timer; - - /* Used in get_payflows to set ids to each pay_flow. */ - u64 next_partid; -}; - -struct renepay *renepay_new(struct command *cmd, +struct payment *payment_new(const tal_t *ctx, + struct command *cmd, const char *invstr TAKES, const char *label TAKES, const char *description TAKES, @@ -144,12 +135,6 @@ struct renepay *renepay_new(struct command *cmd, u64 min_prob_success_millionths, bool use_shadow); -void renepay_cleanup( - struct renepay * renepay, - struct gossmap * gossmap); - -void payment_fail(struct payment * p); -void payment_success(struct payment * p); struct amount_msat payment_sent(const struct payment *p); struct amount_msat payment_delivered(const struct payment *p); struct amount_msat payment_amount(const struct payment *p); @@ -159,13 +144,14 @@ void payment_note(struct payment *p, const char *fmt, ...); void payment_assert_delivering_incomplete(const struct payment *p); void payment_assert_delivering_all(const struct payment *p); -struct command_result *renepay_success(struct renepay *renepay); +struct command_result *payment_success(struct payment *payment); -struct command_result *renepay_fail( - struct renepay * renepay, +struct command_result *payment_fail( + struct payment *payment, enum jsonrpc_errcode code, const char *fmt, ...); -u64 renepay_parts(const struct renepay *renepay); +u64 payment_parts(const struct payment *payment); +void payment_cleanup(struct payment *payment); #endif /* LIGHTNING_PLUGINS_RENEPAY_PAYMENT_H */ diff --git a/plugins/renepay/uncertainty_network.c b/plugins/renepay/uncertainty_network.c index 410e8561d..0d5db6e7a 100644 --- a/plugins/renepay/uncertainty_network.c +++ b/plugins/renepay/uncertainty_network.c @@ -41,7 +41,7 @@ bool uncertainty_network_check_invariants(struct chan_extra_map *chan_extra_map) static void add_hintchan( struct chan_extra_map *chan_extra_map, - struct renepay * renepay, + struct payment *payment, const struct node_id *src, const struct node_id *dst, u16 cltv_expiry_delta, @@ -63,9 +63,9 @@ static void add_hintchan( scid, MAX_CAP); /* FIXME: features? */ - gossmap_local_addchan(renepay->local_gossmods, + gossmap_local_addchan(payment->local_gossmods, src, dst, &scid, NULL); - gossmap_local_updatechan(renepay->local_gossmods, + gossmap_local_updatechan(payment->local_gossmods, &scid, /* We assume any HTLC is allowed */ AMOUNT_MSAT(0), MAX_CAP, @@ -84,15 +84,14 @@ static void add_hintchan( /* Add routehints provided by bolt11 */ void uncertainty_network_add_routehints( struct chan_extra_map *chan_extra_map, - struct renepay *renepay) + struct payment *p) { - const struct payment *const p = renepay->payment; struct bolt11 *b11; char *fail; b11 = bolt11_decode(tmpctx, p->invstr, - plugin_feature_set(renepay->cmd->plugin), + plugin_feature_set(p->cmd->plugin), p->description, chainparams, &fail); if (b11 == NULL) debug_err("add_routehints: Invalid bolt11: %s", fail); @@ -104,7 +103,7 @@ void uncertainty_network_add_routehints( for (int j = tal_count(r)-1; j >= 0; j--) { add_hintchan( chan_extra_map, - renepay, &r[j].pubkey, end, + p, &r[j].pubkey, end, r[j].cltv_expiry_delta, r[j].short_channel_id, r[j].fee_base_msat, @@ -232,11 +231,10 @@ void uncertainty_network_channel_can_send( bool uncertainty_network_update_from_listpeerchannels( struct chan_extra_map * chan_extra_map, struct node_id my_id, - struct renepay * renepay, + struct payment *p, const char *buf, const jsmntok_t *toks) { - struct payment * const p = renepay->payment; const jsmntok_t *channels, *channel; size_t i; @@ -270,7 +268,7 @@ bool uncertainty_network_update_from_listpeerchannels( type_to_string(tmpctx, struct short_channel_id, &scid)); - tal_arr_expand(&renepay->disabled, scid); + tal_arr_expand(&p->disabled, scid); continue; } @@ -302,7 +300,7 @@ bool uncertainty_network_update_from_listpeerchannels( /* Don't report opening/closing channels */ if (!json_tok_streq(buf, statetok, "CHANNELD_NORMAL")) { - tal_arr_expand(&renepay->disabled, scid); + tal_arr_expand(&p->disabled, scid); continue; } @@ -316,9 +314,9 @@ bool uncertainty_network_update_from_listpeerchannels( scid, capacity); /* FIXME: features? */ - gossmap_local_addchan(renepay->local_gossmods, + gossmap_local_addchan(p->local_gossmods, &src, &dst, &scid, NULL); - gossmap_local_updatechan(renepay->local_gossmods, + gossmap_local_updatechan(p->local_gossmods, &scid, /* TODO(eduardo): does it diff --git a/plugins/renepay/uncertainty_network.h b/plugins/renepay/uncertainty_network.h index 6a8a0bffc..d07c627a3 100644 --- a/plugins/renepay/uncertainty_network.h +++ b/plugins/renepay/uncertainty_network.h @@ -14,7 +14,7 @@ bool uncertainty_network_check_invariants(struct chan_extra_map *chan_extra_map) /* Add routehints provided by bolt11 */ void uncertainty_network_add_routehints( struct chan_extra_map *chan_extra_map, - struct renepay *renepay); + struct payment *payment); /* Mirror the gossmap in the public uncertainty network. * result: Every channel in gossmap must have associated data in chan_extra_map, @@ -40,7 +40,7 @@ void uncertainty_network_channel_can_send( bool uncertainty_network_update_from_listpeerchannels( struct chan_extra_map * chan_extra_map, struct node_id my_id, - struct renepay * renepay, + struct payment *payment, const char *buf, const jsmntok_t *toks);