Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Renepay refactor #7588

Draft
wants to merge 3 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
67 changes: 48 additions & 19 deletions plugins/renepay/flow.c
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,8 @@
#define SUPERVERBOSE_ENABLED 1
#endif

struct amount_msat *tal_flow_amounts(const tal_t *ctx, const struct flow *flow)
struct amount_msat *tal_flow_amounts(const tal_t *ctx, const struct flow *flow,
bool compute_fees)
{
const size_t pathlen = tal_count(flow->path);
struct amount_msat *amounts = tal_arr(ctx, struct amount_msat, pathlen);
Expand All @@ -23,7 +24,8 @@ struct amount_msat *tal_flow_amounts(const tal_t *ctx, const struct flow *flow)
for (int i = (int)pathlen - 2; i >= 0; i--) {
const struct half_chan *h = flow_edge(flow, i + 1);
amounts[i] = amounts[i + 1];
if (!amount_msat_add_fee(&amounts[i], h->base_fee,
if (compute_fees &&
!amount_msat_add_fee(&amounts[i], h->base_fee,
h->proportional_fee))
goto function_fail;
}
Expand All @@ -39,11 +41,7 @@ const char *fmt_flows(const tal_t *ctx, const struct gossmap *gossmap,
struct flow **flows)
{
tal_t *this_ctx = tal(ctx, tal_t);
double tot_prob =
flowset_probability(tmpctx, flows, gossmap, chan_extra_map, NULL);
assert(tot_prob >= 0);
char *buff = tal_fmt(ctx, "%zu subflows, prob %2lf\n", tal_count(flows),
tot_prob);
char *buff = tal_fmt(ctx, "%zu subflows\n", tal_count(flows));
for (size_t i = 0; i < tal_count(flows); i++) {
struct amount_msat fee, delivered;
tal_append_fmt(&buff, " ");
Expand Down Expand Up @@ -233,11 +231,20 @@ struct chan_inflight_flow
struct amount_msat half[2];
};

/* @ctx: allocator
* @flows: flows for which the probability is computed
* @gossmap: gossip
* @chan_extra_map: knowledge
* @compute_fees: compute fees along the way or not
* @fail: if a failure occurs, returns a message to the caller
* */
// TODO(eduardo): here chan_extra_map should be const
// TODO(eduardo): here flows should be const
double flowset_probability(const tal_t *ctx, struct flow **flows,
const struct gossmap *const gossmap,
struct chan_extra_map *chan_extra_map, char **fail)
struct chan_extra_map *chan_extra_map,
bool compute_fees,
char **fail)
{
assert(flows);
assert(gossmap);
Expand All @@ -251,14 +258,21 @@ double flowset_probability(const tal_t *ctx, struct flow **flows,
struct chan_inflight_flow *in_flight =
tal_arr(this_ctx, struct chan_inflight_flow, max_num_chans);

if (!in_flight) {
if (fail)
*fail = tal_fmt(ctx, "failed to allocate memory");
goto function_fail;
}

for (size_t i = 0; i < max_num_chans; ++i) {
in_flight[i].half[0] = in_flight[i].half[1] = AMOUNT_MSAT(0);
}

for (size_t i = 0; i < tal_count(flows); ++i) {
const struct flow *f = flows[i];
const size_t pathlen = tal_count(f->path);
struct amount_msat *amounts = tal_flow_amounts(this_ctx, f);
struct amount_msat *amounts =
tal_flow_amounts(this_ctx, f, compute_fees);
if (!amounts)
{
if (fail)
Expand All @@ -284,18 +298,32 @@ double flowset_probability(const tal_t *ctx, struct flow **flows,

const struct amount_msat deliver = amounts[j];

struct amount_msat prev_flow;
struct amount_msat prev_flow, all_inflight;
if (!amount_msat_add(&prev_flow, h->htlc_total,
in_flight[c_idx].half[c_dir])) {
in_flight[c_idx].half[c_dir]) ||
!amount_msat_add(&all_inflight, prev_flow,
deliver)) {
if (fail)
*fail = tal_fmt(
ctx, "in-flight amount_msat overflow");
*fail = tal_fmt(
ctx,
"in-flight amount_msat overflow");
goto function_fail;
}

double edge_prob =
edge_probability(h->known_min, h->known_max,
prev_flow, deliver);
if (!amount_msat_less_eq(all_inflight, h->known_max)) {
if (fail)
*fail = tal_fmt(
ctx,
"in-flight (%s) exceeds known_max "
"(%s)",
fmt_amount_msat(ctx, all_inflight),
fmt_amount_msat(ctx, h->known_max));
goto function_fail;
}

double edge_prob = edge_probability(
h->known_min, h->known_max, prev_flow, deliver);

if (edge_prob < 0) {
if (fail)
*fail = tal_fmt(ctx,
Expand Down Expand Up @@ -406,7 +434,8 @@ bool flow_assign_delivery(struct flow *flow, const struct gossmap *gossmap,
* success provided that there are no other flows in the current MPP flow set.
* */
double flow_probability(struct flow *flow, const struct gossmap *gossmap,
struct chan_extra_map *chan_extra_map)
struct chan_extra_map *chan_extra_map,
bool compute_fees)
{
assert(flow);
assert(gossmap);
Expand All @@ -425,8 +454,8 @@ double flow_probability(struct flow *flow, const struct gossmap *gossmap,

if (prob < 0)
goto function_fail;
if (!amount_msat_add_fee(&spend, h->base_fee,
h->proportional_fee))
if (compute_fees && !amount_msat_add_fee(&spend, h->base_fee,
h->proportional_fee))
goto function_fail;
}

Expand Down
9 changes: 6 additions & 3 deletions plugins/renepay/flow.h
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,8 @@ double flow_edge_cost(const struct gossmap *gossmap,
/* Compute the prob. of success of a set of concurrent set of flows. */
double flowset_probability(const tal_t *ctx, struct flow **flows,
const struct gossmap *const gossmap,
struct chan_extra_map *chan_extra_map, char **fail);
struct chan_extra_map *chan_extra_map,
bool compute_fees, char **fail);

/* How much do we need to send to make this flow arrive. */
bool flow_spend(struct amount_msat *ret, struct flow *flow);
Expand All @@ -63,7 +64,8 @@ static inline struct amount_msat flow_delivers(const struct flow *flow)
return flow->amount;
}

struct amount_msat *tal_flow_amounts(const tal_t *ctx, const struct flow *flow);
struct amount_msat *tal_flow_amounts(const tal_t *ctx, const struct flow *flow,
bool compute_fees);

enum renepay_errorcode
flow_maximum_deliverable(struct amount_msat *max_deliverable,
Expand All @@ -79,7 +81,8 @@ bool flow_assign_delivery(struct flow *flow, const struct gossmap *gossmap,
struct amount_msat requested_amount);

double flow_probability(struct flow *flow, const struct gossmap *gossmap,
struct chan_extra_map *chan_extra_map);
struct chan_extra_map *chan_extra_map,
bool compute_fees);

u64 flow_delay(const struct flow *flow);
u64 flows_worst_delay(struct flow **flows);
Expand Down
14 changes: 10 additions & 4 deletions plugins/renepay/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -24,10 +24,9 @@
// it would be nice if listsendpay would give us the route of pending
// sendpays.

struct pay_plugin *pay_plugin;

static void memleak_mark(struct plugin *p, struct htable *memtable)
{
struct pay_plugin *pay_plugin = get_renepay(p);
memleak_scan_obj(memtable, pay_plugin);
memleak_scan_htable(memtable,
&pay_plugin->uncertainty->chan_extra_map->raw);
Expand All @@ -38,6 +37,7 @@ static void memleak_mark(struct plugin *p, struct htable *memtable)
static const char *init(struct plugin *p,
const char *buf UNUSED, const jsmntok_t *config UNUSED)
{
struct pay_plugin *pay_plugin = get_renepay(p);
size_t num_channel_updates_rejected = 0;

tal_steal(p, pay_plugin);
Expand Down Expand Up @@ -99,6 +99,7 @@ static struct command_result *json_paystatus(struct command *cmd,
const char *buf,
const jsmntok_t *params)
{
struct pay_plugin *pay_plugin = get_renepay(cmd->plugin);
const char *invstring;
struct json_stream *ret;

Expand Down Expand Up @@ -155,6 +156,8 @@ static struct command_result * payment_start(struct payment *p)
{
assert(p);
p->status = PAYMENT_PENDING;
struct pay_plugin *pay_plugin = get_renepay(p->plugin);
assert(pay_plugin);
plugin_log(pay_plugin->plugin, LOG_DBG, "Starting renepay");
p->exec_state = 0;
return payment_continue(p);
Expand All @@ -163,6 +166,8 @@ static struct command_result * payment_start(struct payment *p)
static struct command_result *json_pay(struct command *cmd, const char *buf,
const jsmntok_t *params)
{
struct pay_plugin *pay_plugin = get_renepay(cmd->plugin);
assert(pay_plugin);
/* === Parse command line arguments === */
// TODO check if we leak some of these temporary variables

Expand Down Expand Up @@ -312,6 +317,7 @@ static struct command_result *json_pay(struct command *cmd, const char *buf,
{
payment = payment_new(
tmpctx,
cmd->plugin,
&b11->payment_hash,
take(invstr),
take(label),
Expand Down Expand Up @@ -419,12 +425,12 @@ int main(int argc, char *argv[])
setup_locale();

/* Most gets initialized in init(), but set debug options here. */
pay_plugin = tal(NULL, struct pay_plugin);
struct pay_plugin *pay_plugin = tal(NULL, struct pay_plugin);
pay_plugin->debug_mcf = pay_plugin->debug_payflow = false;

plugin_main(
argv,
init, NULL,
init, pay_plugin,
PLUGIN_RESTARTABLE,
/* init_rpc */ true,
/* features */ NULL,
Expand Down
23 changes: 15 additions & 8 deletions plugins/renepay/mcf.c
Original file line number Diff line number Diff line change
Expand Up @@ -470,8 +470,14 @@ static bool linearize_channel(const struct pay_parameters *params,
return false;
}

assert(
amount_msat_less_eq(extra_half->htlc_total, extra_half->known_max));
/* FIXME: this assertion has been reported to be triggered in issue
* #7535. A quick and dirty solution is to comment it and work-around
* this case. But in principle if we do things the right way we should
* not have htlc_total>known_max. The problem is likely to be
* asynchronous way in which reserved htlcs are removed and known_max is
* updated. */
// assert(
// amount_msat_less_eq(extra_half->htlc_total, extra_half->known_max));
assert(
amount_msat_less_eq(extra_half->known_min, extra_half->known_max));

Expand Down Expand Up @@ -1443,9 +1449,8 @@ get_flow_paths(const tal_t *ctx, const struct gossmap *gossmap,
excess = amount_msat(0);
fp->amount = delivered;


fp->success_prob =
flow_probability(fp, gossmap, chan_extra_map)
flow_probability(fp, gossmap, chan_extra_map, false)
* pow(base_probability, tal_count(fp->path));
if (fp->success_prob < 0) {
if (fail)
Expand Down Expand Up @@ -1731,12 +1736,14 @@ struct flow **minflow(const tal_t *ctx, struct gossmap *gossmap,

best_prob_success =
flowset_probability(this_ctx, best_flow_paths, params->gossmap,
params->chan_extra_map, &errmsg)
params->chan_extra_map, false, &errmsg)
* pow(params->base_probability, flowset_size(best_flow_paths));
if (best_prob_success < 0) {
if (fail)
*fail =
tal_fmt(ctx, "flowset_probability failed: %s", errmsg);
*fail = tal_fmt(
ctx,
"flowset_probability failed on MaxFlow phase: %s",
errmsg);
goto function_fail;
}
if (!flowset_fee(&best_fee, best_flow_paths)) {
Expand Down Expand Up @@ -1789,7 +1796,7 @@ struct flow **minflow(const tal_t *ctx, struct gossmap *gossmap,

double prob_success =
flowset_probability(this_ctx, flow_paths, params->gossmap,
params->chan_extra_map, &errmsg)
params->chan_extra_map, false, &errmsg)
* pow(params->base_probability, flowset_size(flow_paths));
if (prob_success < 0) {
// flowset_probability doesn't fail unless there is a bug.
Expand Down
Loading
Loading