core-lightning/plugins/renepay/payment.c
Rusty Russell 0a9b3d6740 renepay: remove attempt limit.
Time is what users care about, so remove this.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2023-08-12 09:41:24 +09:30

214 lines
5.7 KiB
C

#include "config.h"
#include <ccan/ccan/tal/str/str.h>
#include <plugins/renepay/debug.h>
#include <plugins/renepay/payment.h>
struct payment * payment_new(struct renepay * renepay)
{
struct payment *p = tal(renepay,struct payment);
p->renepay = renepay;
p->paynotes = tal_arr(p, const char *, 0);
p->total_sent = AMOUNT_MSAT(0);
p->total_delivering = AMOUNT_MSAT(0);
p->invstr=NULL;
p->amount = AMOUNT_MSAT(0);
// p->destination=
// p->payment_hash
p->maxspend = AMOUNT_MSAT(0);
p->maxdelay=0;
// p->start_time=
// p->stop_time=
p->preimage = NULL;
p->payment_secret=NULL;
p->payment_metadata=NULL;
p->status=PAYMENT_PENDING;
p->final_cltv=0;
// p->list=
p->description=NULL;
p->label=NULL;
p->delay_feefactor=0;
p->base_fee_penalty=0;
p->prob_cost_factor=0;
p->min_prob_success=0;
p->local_offer_id=NULL;
p->use_shadow=true;
p->groupid=1;
p->result = NULL;
return p;
}
struct renepay * renepay_new(struct command *cmd)
{
struct renepay *renepay = tal(cmd,struct renepay);
renepay->cmd = cmd;
renepay->payment = payment_new(renepay);
renepay->localmods_applied=false;
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;
}
struct amount_msat payment_delivered(const struct payment *p)
{
return p->total_delivering;
}
struct amount_msat payment_amount(const struct payment *p)
{
return p->amount;
}
struct amount_msat payment_fees(const struct payment *p)
{
struct amount_msat fees;
struct amount_msat sent = payment_sent(p),
delivered = payment_delivered(p);
if(!amount_msat_sub(&fees,sent,delivered))
debug_err( "Strange, sent amount (%s) is less than delivered (%s), aborting.",
type_to_string(tmpctx,struct amount_msat,&sent),
type_to_string(tmpctx,struct amount_msat,&delivered));
return fees;
}
void payment_note(struct payment *p, const char *fmt, ...)
{
va_list ap;
const char *str;
va_start(ap, fmt);
str = tal_vfmt(p->paynotes, fmt, ap);
va_end(ap);
tal_arr_expand(&p->paynotes, str);
debug_info("%s",str);
}
void payment_assert_delivering_incomplete(const struct payment *p)
{
if(!amount_msat_less(p->total_delivering, p->amount))
{
debug_err(
"Strange, delivering (%s) is not smaller than amount (%s)",
type_to_string(tmpctx,struct amount_msat,&p->total_delivering),
type_to_string(tmpctx,struct amount_msat,&p->amount));
}
}
void payment_assert_delivering_all(const struct payment *p)
{
if(amount_msat_less(p->total_delivering, p->amount))
{
debug_err(
"Strange, delivering (%s) is less than amount (%s)",
type_to_string(tmpctx,struct amount_msat,&p->total_delivering),
type_to_string(tmpctx,struct amount_msat,&p->amount));
}
}
struct command_result *renepay_success(struct renepay * renepay)
{
debug_info("calling %s",__PRETTY_FUNCTION__);
struct payment *p = renepay->payment;
payment_success(p);
payment_assert_delivering_all(p);
struct json_stream *response
= jsonrpc_stream_success(renepay->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_amount_msat(response, "amount_msat",
p->amount);
json_add_amount_msat(response, "amount_sent_msat",
p->total_sent);
json_add_string(response, "status", "complete");
json_add_node_id(response, "destination", &p->destination);
return command_finished(renepay->cmd, response);
}
struct command_result *renepay_fail(
struct renepay * renepay,
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);
va_list args;
va_start(args, fmt);
char *message = tal_vfmt(tmpctx,fmt,args);
va_end(args);
debug_paynote(renepay->payment,"%s",message);
return command_fail(renepay->cmd,code,"%s",message);
}
u64 renepay_parts(const struct renepay *renepay)
{
return renepay->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)
{
debug_info("calling %s",__PRETTY_FUNCTION__);
/* Always remove our local mods (routehints) so others can use
* gossmap. We do this only after the payment completes. */
// 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.
if(renepay->localmods_applied)
gossmap_remove_localmods(gossmap,
renepay->local_gossmods);
// TODO(eduardo): I wonder if it is possible to have two instances of
// renepay at the same time.
// 1st problem: dijkstra datastructure is global, this can be fixed,
// 2nd problem: we don't know if gossmap_apply_localmods and gossmap_remove_localmods,
// can handle different local_gossmods applied to the same gossmap.
renepay->localmods_applied=false;
tal_free(renepay->local_gossmods);
renepay->rexmit_timer = tal_free(renepay->rexmit_timer);
if(renepay->payment)
renepay->payment->renepay = NULL;
}