uniform error handling pattern for flow.c

This commit is contained in:
Lagrang3 2023-12-18 14:18:00 +01:00 committed by Rusty Russell
parent af3bcddc1f
commit 1f6772160f
10 changed files with 679 additions and 449 deletions

File diff suppressed because it is too large Load Diff

View File

@ -121,7 +121,7 @@ const char *fmt_chan_extra_map(
/* Returns "" if nothing useful known about channel, otherwise
* "(details)" */
const char *fmt_chan_extra_details(const tal_t *ctx,
struct chan_extra_map* chan_extra_map,
const struct chan_extra_map* chan_extra_map,
const struct short_channel_id_dir *scidd);
/* Creates a new chan_extra and adds it to the chan_extra_map. */
@ -131,12 +131,6 @@ struct chan_extra *new_chan_extra(
struct amount_msat capacity);
/* This helper function preserves the uncertainty network invariant after the
* knowledge is updated. It assumes that the (channel,!dir) knowledge is
* correct. */
void chan_extra_adjust_half(struct chan_extra *ce,
int dir);
/* Helper to find the min of two amounts */
static inline struct amount_msat amount_msat_min(
struct amount_msat a,
@ -153,36 +147,32 @@ static inline struct amount_msat amount_msat_max(
}
/* Update the knowledge that this (channel,direction) can send x msat.*/
void chan_extra_can_send(struct chan_extra_map *chan_extra_map,
bool chan_extra_can_send(const tal_t *ctx,
struct chan_extra_map *chan_extra_map,
const struct short_channel_id_dir *scidd,
struct amount_msat x);
struct amount_msat x, char **fail);
/* Update the knowledge that this (channel,direction) cannot send x msat.*/
void chan_extra_cannot_send(struct chan_extra_map *chan_extra_map,
bool chan_extra_cannot_send(const tal_t *ctx,
struct chan_extra_map *chan_extra_map,
const struct short_channel_id_dir *scidd,
struct amount_msat x);
struct amount_msat sent, char **fail);
/* Update the knowledge that this (channel,direction) has liquidity x.*/
void chan_extra_set_liquidity(struct chan_extra_map *chan_extra_map,
bool chan_extra_set_liquidity(const tal_t *ctx,
struct chan_extra_map *chan_extra_map,
const struct short_channel_id_dir *scidd,
struct amount_msat x);
struct amount_msat x, char **fail);
/* Update the knowledge that this (channel,direction) has sent x msat.*/
void chan_extra_sent_success(struct chan_extra_map *chan_extra_map,
bool chan_extra_sent_success(const tal_t *ctx,
struct chan_extra_map *chan_extra_map,
const struct short_channel_id_dir *scidd,
struct amount_msat x);
/* Forget a bit about this (channel,direction) state. */
void chan_extra_relax(struct chan_extra_map *chan_extra_map,
const struct short_channel_id_dir *scidd,
struct amount_msat down,
struct amount_msat up);
struct amount_msat x, char **fail);
/* Forget the channel information by a fraction of the capacity. */
void chan_extra_relax_fraction(
struct chan_extra* ce,
double fraction);
bool chan_extra_relax_fraction(const tal_t *ctx, struct chan_extra *ce,
double fraction, char **fail);
/* Returns either NULL, or an entry from the hash */
struct chan_extra_half *get_chan_extra_half_by_scid(struct chan_extra_map *chan_extra_map,
@ -232,30 +222,30 @@ double flow_edge_cost(const struct gossmap *gossmap,
double delay_riskfactor);
/* Function to fill in amounts and success_prob for flow. */
void flow_complete(struct flow *flow,
bool flow_complete(const tal_t *ctx, struct flow *flow,
const struct gossmap *gossmap,
struct chan_extra_map *chan_extra_map,
struct amount_msat delivered);
struct amount_msat delivered, char **fail);
/* Compute the prob. of success of a set of concurrent set of flows. */
double flow_set_probability(
struct flow ** flows,
const struct gossmap *const gossmap,
struct chan_extra_map * chan_extra_map);
double flowset_probability(const tal_t *ctx, struct flow **flows,
const struct gossmap *const gossmap,
struct chan_extra_map *chan_extra_map, char **fail);
// TODO(eduardo): we probably don't need this. Instead we should have payflow
// input.
/* Once flow is completed, this can remove it from the extra_map */
void remove_completed_flow(const struct gossmap *gossmap,
bool remove_completed_flow(const tal_t *ctx, const struct gossmap *gossmap,
struct chan_extra_map *chan_extra_map,
struct flow *flow);
struct flow *flow, char **fail);
// TODO(eduardo): we probably don't need this. Instead we should have payflow
// input.
void remove_completed_flow_set(const struct gossmap *gossmap,
struct chan_extra_map *chan_extra_map,
struct flow **flows);
bool remove_completed_flowset(const tal_t *ctx, const struct gossmap *gossmap,
struct chan_extra_map *chan_extra_map,
struct flow **flows, char **fail);
struct amount_msat flow_set_fee(struct flow **flows);
bool flowset_fee(struct amount_msat *fee, struct flow **flows);
/*
* mu (μ) is used as follows in the cost function:
@ -307,17 +297,15 @@ s64 linear_fee_cost(
// TODO(eduardo): we probably don't need this. Instead we should have payflow
// input.
/* Take the flows and commit them to the chan_extra's . */
void commit_flow(
const struct gossmap *gossmap,
struct chan_extra_map *chan_extra_map,
struct flow *flow);
bool commit_flow(const tal_t *ctx, const struct gossmap *gossmap,
struct chan_extra_map *chan_extra_map, struct flow *flow,
char **fail);
// TODO(eduardo): we probably don't need this. Instead we should have payflow
// input.
/* Take the flows and commit them to the chan_extra's . */
void commit_flow_set(
const struct gossmap *gossmap,
struct chan_extra_map *chan_extra_map,
struct flow **flows);
bool commit_flowset(const tal_t *ctx, const struct gossmap *gossmap,
struct chan_extra_map *chan_extra_map, struct flow **flows,
char **fail);
#endif /* LIGHTNING_PLUGINS_RENEPAY_FLOW_H */

View File

@ -1122,6 +1122,7 @@ static struct flow **
// in the MCF solver
struct amount_msat excess)
{
char *errmsg;
assert(amount_msat_less(excess, AMOUNT_MSAT(1000)));
tal_t *this_ctx = tal(tmpctx,tal_t);
@ -1250,7 +1251,13 @@ static struct flow **
// complete the flow path by adding real fees and
// probabilities.
flow_complete(fp,gossmap,chan_extra_map,delivered);
if (!flow_complete(tmpctx, fp, gossmap, chan_extra_map,
delivered, &errmsg)) {
plugin_err(
pay_plugin->plugin,
"%s (line %d) flow_complete failed: %s",
__PRETTY_FUNCTION__, __LINE__, errmsg);
}
// add fp to flows
tal_arr_expand(&flows, fp);
@ -1381,6 +1388,7 @@ struct flow** minflow(
u32 prob_cost_factor )
{
tal_t *this_ctx = tal(tmpctx,tal_t);
char *errmsg;
struct pay_parameters *params = tal(this_ctx,struct pay_parameters);
struct dijkstra *dijkstra;
@ -1467,10 +1475,19 @@ struct flow** minflow(
best_flow_paths = get_flow_paths(ctx,params->gossmap,params->chan_extra_map,
linear_network,residual_network,
excess);
best_prob_success = flow_set_probability(best_flow_paths,
params->gossmap,
params->chan_extra_map);
best_fee = flow_set_fee(best_flow_paths);
best_prob_success =
flowset_probability(tmpctx, best_flow_paths, params->gossmap,
params->chan_extra_map, &errmsg);
if (best_prob_success < 0) {
plugin_err(pay_plugin->plugin,
"%s (line %d) flowset_probability failed: %s",
__PRETTY_FUNCTION__, __LINE__, errmsg);
}
if (!flowset_fee(&best_fee, best_flow_paths)) {
plugin_err(pay_plugin->plugin,
"%s (line %d) flowset_fee failed",
__PRETTY_FUNCTION__, __LINE__, errmsg);
}
// binary search for a value of `mu` that fits our fee and prob.
// constraints.
@ -1492,11 +1509,22 @@ struct flow** minflow(
linear_network,residual_network,
excess);
double prob_success = flow_set_probability(
flow_paths,
params->gossmap,
params->chan_extra_map);
struct amount_msat fee = flow_set_fee(flow_paths);
double prob_success =
flowset_probability(tmpctx, flow_paths, params->gossmap,
params->chan_extra_map, &errmsg);
if (prob_success < 0) {
plugin_err(
pay_plugin->plugin,
"%s (line %d) flowset_probability failed: %s",
__PRETTY_FUNCTION__, __LINE__, errmsg);
}
struct amount_msat fee;
if (!flowset_fee(&fee, flow_paths)) {
plugin_err(pay_plugin->plugin,
"%s (line %d) flowset_fee failed",
__PRETTY_FUNCTION__, __LINE__, errmsg);
}
/* Is this better than the previous one? */
if(!best_flow_paths ||

View File

@ -1125,11 +1125,28 @@ static void handle_sendpay_failure_flow(struct pay_flow *pf,
if((enum onion_wire)onionerr == WIRE_TEMPORARY_CHANNEL_FAILURE
&& erridx < tal_count(pf->path_scidds))
{
chan_extra_cannot_send(pay_plugin->chan_extra_map,
&pf->path_scidds[erridx],
pf->amounts[erridx]);
// TODO: notify the plugin of the changes to the uncertainty
// network
const char *old_state =
fmt_chan_extra_details(tmpctx, pay_plugin->chan_extra_map,
&pf->path_scidds[erridx]);
char *fail;
if (!chan_extra_cannot_send(tmpctx, pay_plugin->chan_extra_map,
&pf->path_scidds[erridx],
pf->amounts[erridx], &fail)) {
plugin_err(pay_plugin->plugin,
"chan_extra_cannot_send failed: %s", fail);
}
payflow_note(pf, LOG_INFORM,
"Failure to forward amount %s in channel %s, "
"state change %s -> %s",
fmt_amount_msat(tmpctx, pf->amounts[erridx]),
type_to_string(tmpctx, struct short_channel_id_dir,
&pf->path_scidds[erridx]),
old_state,
fmt_chan_extra_details(tmpctx,
pay_plugin->chan_extra_map,
&pf->path_scidds[erridx]));
}
}

View File

@ -491,8 +491,19 @@ const char *add_payflows(const tal_t *ctx,
}
/* Are we unhappy? */
prob = flow_set_probability(flows,pay_plugin->gossmap,pay_plugin->chan_extra_map);
fee = flow_set_fee(flows);
char *fail;
prob = flowset_probability(tmpctx, flows, pay_plugin->gossmap,
pay_plugin->chan_extra_map, &fail);
if(prob<0)
{
plugin_err(pay_plugin->plugin,
"flow_set_probability failed: %s", fail);
}
if(!flowset_fee(&fee,flows))
{
plugin_err(pay_plugin->plugin,
"flowset_fee failed");
}
delay = flows_worst_delay(flows) + p->final_cltv;
payment_note(p, LOG_INFORM,

View File

@ -13,20 +13,19 @@
/* AUTOGENERATED MOCKS START */
/* Generated stub for flow_complete */
void flow_complete(struct flow *flow UNNEEDED,
bool flow_complete(const tal_t *ctx UNNEEDED, struct flow *flow UNNEEDED,
const struct gossmap *gossmap UNNEEDED,
struct chan_extra_map *chan_extra_map UNNEEDED,
struct amount_msat delivered UNNEEDED)
struct amount_msat delivered UNNEEDED, char **fail UNNEEDED)
{ fprintf(stderr, "flow_complete called!\n"); abort(); }
/* Generated stub for flow_set_fee */
struct amount_msat flow_set_fee(struct flow **flows UNNEEDED)
{ fprintf(stderr, "flow_set_fee called!\n"); abort(); }
/* Generated stub for flow_set_probability */
double flow_set_probability(
struct flow ** flows UNNEEDED,
const struct gossmap *const gossmap UNNEEDED,
struct chan_extra_map * chan_extra_map UNNEEDED)
{ fprintf(stderr, "flow_set_probability called!\n"); abort(); }
/* Generated stub for flowset_fee */
bool flowset_fee(struct amount_msat *fee UNNEEDED, struct flow **flows UNNEEDED)
{ fprintf(stderr, "flowset_fee called!\n"); abort(); }
/* Generated stub for flowset_probability */
double flowset_probability(const tal_t *ctx UNNEEDED, struct flow **flows UNNEEDED,
const struct gossmap *const gossmap UNNEEDED,
struct chan_extra_map *chan_extra_map UNNEEDED, char **fail UNNEEDED)
{ fprintf(stderr, "flowset_probability called!\n"); abort(); }
/* Generated stub for get_chan_extra_half_by_chan */
struct chan_extra_half *get_chan_extra_half_by_chan(const struct gossmap *gossmap UNNEEDED,
struct chan_extra_map *chan_extra_map UNNEEDED,

View File

@ -39,7 +39,9 @@ static const char* print_flows(
struct flow **flows)
{
tal_t *this_ctx = tal(ctx,tal_t);
double tot_prob = flow_set_probability(flows,gossmap,chan_extra_map);
double tot_prob =
flowset_probability(tmpctx, flows, gossmap, chan_extra_map, NULL);
assert(tot_prob>=0);
char *buff = tal_fmt(ctx,"%s: %zu subflows, prob %2lf\n", desc, tal_count(flows),tot_prob);
for (size_t i = 0; i < tal_count(flows); i++) {
struct amount_msat fee, delivered;

View File

@ -355,7 +355,11 @@ int main(int argc, char *argv[])
/* delay fee factor = */ 1,
/* base fee penalty */ 1,
/* prob cost factor = */ 10);
commit_flow_set(gossmap,chan_extra_map,flows);
if(!commit_flowset(tmpctx, gossmap,chan_extra_map,flows,NULL))
{
assert(0 && "commit_flowset failed");
}
printf("%s\n",
print_flows(tmpctx,"Flow via single path l1->l2->l3", gossmap, flows));
@ -406,7 +410,10 @@ int main(int argc, char *argv[])
assert(amount_msat_eq(ce->half[1].known_max, AMOUNT_MSAT(1000000000)));
/* Clear that */
remove_completed_flow_set(gossmap, chan_extra_map, flows);
if(!remove_completed_flowset(tmpctx, gossmap, chan_extra_map, flows,NULL))
{
assert(0 && "remove_completed_flowset failed");
}
// /* Now try adding a local channel scid */

View File

@ -394,40 +394,40 @@ static void test_edge_probability(void)
{
f.millisatoshis = i;
// prob = 1
assert(fabs(edge_probability(min,max,X,f)-1.0)< eps);
assert(fabs(edge_probability(tmpctx,min,max,X,f, NULL)-1.0)< eps);
}
for(int i=max.millisatoshis+1;i<=100;++i)
{
f.millisatoshis = i;
// prob = 0
assert(fabs(edge_probability(min,max,X,f))< eps);
assert(fabs(edge_probability(tmpctx,min,max,X,f, NULL))< eps);
}
f.millisatoshis=11;
assert(fabs(edge_probability(min,max,X,f)-0.9)< eps);
assert(fabs(edge_probability(tmpctx,min,max,X,f,NULL)-0.9)< eps);
f.millisatoshis=12;
assert(fabs(edge_probability(min,max,X,f)-0.8)< eps);
assert(fabs(edge_probability(tmpctx,min,max,X,f,NULL)-0.8)< eps);
f.millisatoshis=13;
assert(fabs(edge_probability(min,max,X,f)-0.7)< eps);
assert(fabs(edge_probability(tmpctx,min,max,X,f,NULL)-0.7)< eps);
f.millisatoshis=14;
assert(fabs(edge_probability(min,max,X,f)-0.6)< eps);
assert(fabs(edge_probability(tmpctx,min,max,X,f,NULL)-0.6)< eps);
f.millisatoshis=15;
assert(fabs(edge_probability(min,max,X,f)-0.5)< eps);
assert(fabs(edge_probability(tmpctx,min,max,X,f,NULL)-0.5)< eps);
f.millisatoshis=16;
assert(fabs(edge_probability(min,max,X,f)-0.4)< eps);
assert(fabs(edge_probability(tmpctx,min,max,X,f,NULL)-0.4)< eps);
f.millisatoshis=17;
assert(fabs(edge_probability(min,max,X,f)-0.3)< eps);
assert(fabs(edge_probability(tmpctx,min,max,X,f,NULL)-0.3)< eps);
f.millisatoshis=18;
assert(fabs(edge_probability(min,max,X,f)-0.2)< eps);
assert(fabs(edge_probability(tmpctx,min,max,X,f,NULL)-0.2)< eps);
f.millisatoshis=19;
assert(fabs(edge_probability(min,max,X,f)-0.1)< eps);
assert(fabs(edge_probability(tmpctx,min,max,X,f,NULL)-0.1)< eps);
X = AMOUNT_MSAT(5);
@ -436,34 +436,34 @@ static void test_edge_probability(void)
{
f.millisatoshis = i;
// prob = 1
assert(fabs(edge_probability(min,max,X,f)-1.0)< eps);
assert(fabs(edge_probability(tmpctx,min,max,X,f,NULL)-1.0)< eps);
}
// X<A, f>=B-X
for(int i=15;i<100;++i)
{
f.millisatoshis = i;
// prob = 0
assert(fabs(edge_probability(min,max,X,f))< eps);
assert(fabs(edge_probability(tmpctx,min,max,X,f,NULL))< eps);
}
// X<A, A-X<=f<=B-X
f.millisatoshis=6;
assert(fabs(edge_probability(min,max,X,f)-0.9)< eps);
assert(fabs(edge_probability(tmpctx,min,max,X,f,NULL)-0.9)< eps);
f.millisatoshis=7;
assert(fabs(edge_probability(min,max,X,f)-0.8)< eps);
assert(fabs(edge_probability(tmpctx,min,max,X,f,NULL)-0.8)< eps);
f.millisatoshis=8;
assert(fabs(edge_probability(min,max,X,f)-0.7)< eps);
assert(fabs(edge_probability(tmpctx,min,max,X,f,NULL)-0.7)< eps);
f.millisatoshis=9;
assert(fabs(edge_probability(min,max,X,f)-0.6)< eps);
assert(fabs(edge_probability(tmpctx,min,max,X,f,NULL)-0.6)< eps);
f.millisatoshis=10;
assert(fabs(edge_probability(min,max,X,f)-0.5)< eps);
assert(fabs(edge_probability(tmpctx,min,max,X,f,NULL)-0.5)< eps);
f.millisatoshis=11;
assert(fabs(edge_probability(min,max,X,f)-0.4)< eps);
assert(fabs(edge_probability(tmpctx,min,max,X,f,NULL)-0.4)< eps);
f.millisatoshis=12;
assert(fabs(edge_probability(min,max,X,f)-0.3)< eps);
assert(fabs(edge_probability(tmpctx,min,max,X,f,NULL)-0.3)< eps);
f.millisatoshis=13;
assert(fabs(edge_probability(min,max,X,f)-0.2)< eps);
assert(fabs(edge_probability(tmpctx,min,max,X,f,NULL)-0.2)< eps);
f.millisatoshis=14;
assert(fabs(edge_probability(min,max,X,f)-0.1)< eps);
assert(fabs(edge_probability(tmpctx,min,max,X,f,NULL)-0.1)< eps);
X = AMOUNT_MSAT(15);
@ -471,22 +471,22 @@ static void test_edge_probability(void)
for(int i=5;i<100;++i)
{
f.millisatoshis = i;
assert(fabs(edge_probability(min,max,X,f))< eps);
assert(fabs(edge_probability(tmpctx,min,max,X,f,NULL))< eps);
}
// X>=A, 0<=f<=B-X
f.millisatoshis=0;
assert(fabs(edge_probability(min,max,X,f)-1.0)< eps);
assert(fabs(edge_probability(tmpctx,min,max,X,f,NULL)-1.0)< eps);
f.millisatoshis=1;
assert(fabs(edge_probability(min,max,X,f)-0.8)< eps);
assert(fabs(edge_probability(tmpctx,min,max,X,f,NULL)-0.8)< eps);
f.millisatoshis=2;
assert(fabs(edge_probability(min,max,X,f)-0.6)< eps);
assert(fabs(edge_probability(tmpctx,min,max,X,f,NULL)-0.6)< eps);
f.millisatoshis=3;
assert(fabs(edge_probability(min,max,X,f)-0.4)< eps);
assert(fabs(edge_probability(tmpctx,min,max,X,f,NULL)-0.4)< eps);
f.millisatoshis=4;
assert(fabs(edge_probability(min,max,X,f)-0.2)< eps);
assert(fabs(edge_probability(tmpctx,min,max,X,f,NULL)-0.2)< eps);
f.millisatoshis=5;
assert(fabs(edge_probability(min,max,X,f)-0.0)< eps);
assert(fabs(edge_probability(tmpctx,min,max,X,f,NULL)-0.0)< eps);
}
static void remove_file(char *fname)
@ -557,10 +557,12 @@ static void test_flow_complete(void)
assert(gossmap_chan_get_capacity(gossmap,c,&cap));
h0 = get_chan_extra_half_by_chan_verify(gossmap,chan_extra_map,c,0);
assert(h0);
h0->known_min = AMOUNT_MSAT(0);
h0->known_max = AMOUNT_MSAT(500000000);
h1 = get_chan_extra_half_by_chan_verify(gossmap,chan_extra_map,c,1);
assert(h1);
h1->known_min = AMOUNT_MSAT(500000000);
h1->known_max = AMOUNT_MSAT(1000000000);
@ -578,10 +580,12 @@ static void test_flow_complete(void)
assert(gossmap_chan_get_capacity(gossmap,c,&cap));
h1 = get_chan_extra_half_by_chan_verify(gossmap,chan_extra_map,c,1);
assert(h1);
h1->known_min = AMOUNT_MSAT(0);
h1->known_max = AMOUNT_MSAT(2000000000);
h0 = get_chan_extra_half_by_chan_verify(gossmap,chan_extra_map,c,0);
assert(h0);
h0->known_min = AMOUNT_MSAT(0);
h0->known_max = AMOUNT_MSAT(2000000000);
@ -599,10 +603,12 @@ static void test_flow_complete(void)
assert(gossmap_chan_get_capacity(gossmap,c,&cap));
h0 = get_chan_extra_half_by_chan_verify(gossmap,chan_extra_map,c,0);
assert(h0);
h0->known_min = AMOUNT_MSAT(500000000);
h0->known_max = AMOUNT_MSAT(1000000000);
h1 = get_chan_extra_half_by_chan_verify(gossmap,chan_extra_map,c,1);
assert(h1);
h1->known_min = AMOUNT_MSAT(0);
h1->known_max = AMOUNT_MSAT(500000000);
@ -620,10 +626,12 @@ static void test_flow_complete(void)
assert(gossmap_chan_get_capacity(gossmap,c,&cap));
h0 = get_chan_extra_half_by_chan_verify(gossmap,chan_extra_map,c,0);
assert(h0);
h0->known_min = AMOUNT_MSAT(1000000000);
h0->known_max = AMOUNT_MSAT(2000000000);
h1 = get_chan_extra_half_by_chan_verify(gossmap,chan_extra_map,c,1);
assert(h1);
h1->known_min = AMOUNT_MSAT(1000000000);
h1->known_max = AMOUNT_MSAT(2000000000);
@ -645,7 +653,9 @@ static void test_flow_complete(void)
F->path[0]=gossmap_find_chan(gossmap,&scid12);
F->dirs[0]=0;
deliver = AMOUNT_MSAT(250000000);
flow_complete(F,gossmap,chan_extra_map,deliver);
if (!flow_complete(tmpctx, F, gossmap, chan_extra_map, deliver, NULL)) {
assert(0 && "flow_complete fail");
}
assert(amount_msat_eq(F->amounts[0],deliver));
assert(fabs(F->success_prob - 0.5)<eps);
@ -657,7 +667,9 @@ static void test_flow_complete(void)
F->dirs[0]=0;
F->dirs[1]=0;
deliver = AMOUNT_MSAT(250000000);
flow_complete(F,gossmap,chan_extra_map,deliver);
if (!flow_complete(tmpctx, F, gossmap, chan_extra_map, deliver, NULL)) {
assert(0 && "flow_complete fail");
}
assert(amount_msat_eq(F->amounts[0],amount_msat(250050016)));
assert(fabs(F->success_prob - 1.)<eps);
@ -671,7 +683,9 @@ static void test_flow_complete(void)
F->dirs[1]=0;
F->dirs[2]=0;
deliver = AMOUNT_MSAT(250000000);
flow_complete(F,gossmap,chan_extra_map,deliver);
if (!flow_complete(tmpctx, F, gossmap, chan_extra_map, deliver, NULL)) {
assert(0 && "flow_complete fail");
}
assert(amount_msat_eq(F->amounts[0],amount_msat(250087534)));
assert(fabs(F->success_prob - 1. + 250.087534/2000)<eps);
@ -687,7 +701,9 @@ static void test_flow_complete(void)
F->dirs[2]=0;
F->dirs[3]=0;
deliver = AMOUNT_MSAT(250000000);
flow_complete(F,gossmap,chan_extra_map,deliver);
if (!flow_complete(tmpctx, F, gossmap, chan_extra_map, deliver, NULL)) {
assert(0 && "flow_complete fail");
}
assert(amount_msat_eq(F->amounts[0],amount_msat(250112544)));
assert(fabs(F->success_prob - 0.43728117)<eps);

View File

@ -190,21 +190,29 @@ void uncertainty_network_flow_success(
struct chan_extra_map *chan_extra_map,
struct pay_flow *pf)
{
char *errmsg;
for (size_t i = 0; i < tal_count(pf->path_scidds); i++)
{
chan_extra_sent_success(
chan_extra_map,
&pf->path_scidds[i],
pf->amounts[i]);
// TODO notify the payflow
// payflow_note(pf, LOG_DBG,
// "Success of %s for %s capacity [%s,%s] -> [%s,%s]",
// fmt_amount_msat(tmpctx, x),
// type_to_string(tmpctx,struct short_channel_id_dir,scidd),
// fmt_amount_msat(tmpctx, ce->half[scidd->dir].known_min),
// fmt_amount_msat(tmpctx, ce->half[scidd->dir].known_max),
// fmt_amount_msat(tmpctx, new_a),
// fmt_amount_msat(tmpctx, new_b));
const char *old_state
= fmt_chan_extra_details(tmpctx, pay_plugin->chan_extra_map,
&pf->path_scidds[i]);
if (!chan_extra_sent_success(tmpctx, chan_extra_map,
&pf->path_scidds[i],
pf->amounts[i], &errmsg)) {
plugin_err(pay_plugin->plugin,
"chan_extra_sent_success failed: %s",
errmsg);
}
payflow_note(pf, LOG_INFORM,
"Success forwarding amount %s in channel %s, "
"state change %s -> %s",
fmt_amount_msat(tmpctx, pf->amounts[i]),
type_to_string(tmpctx, struct short_channel_id_dir,
&pf->path_scidds[i]),
old_state,
fmt_chan_extra_details(tmpctx,
pay_plugin->chan_extra_map,
&pf->path_scidds[i]));
}
}
/* All parts up to erridx succeeded, so we know something about min
@ -214,15 +222,19 @@ void uncertainty_network_channel_can_send(
struct pay_flow *pf,
u32 erridx)
{
char *fail;
for (size_t i = 0; i < erridx; i++)
{
chan_extra_can_send(chan_extra_map,
&pf->path_scidds[i],
/* This channel can send all that was
* commited in HTLCs.
* Had we removed the commited amount then
* we would have to put here pf->amounts[i]. */
AMOUNT_MSAT(0));
if (!chan_extra_can_send(
tmpctx, chan_extra_map, &pf->path_scidds[i],
/* This channel can send all that was
* commited in HTLCs.
* Had we removed the commited amount then
* we would have to put here pf->amounts[i]. */
AMOUNT_MSAT(0), &fail)) {
plugin_err(pay_plugin->plugin,
"chan_extra_can_send failed: %s", fail);
}
}
}
@ -235,6 +247,7 @@ void uncertainty_network_update_from_listpeerchannels(struct payment *p,
struct chan_extra_map *chan_extra_map)
{
struct chan_extra *ce;
char *errmsg;
if (!enabled) {
payment_disable_chan(p, scidd->scid, LOG_DBG,
@ -263,19 +276,29 @@ void uncertainty_network_update_from_listpeerchannels(struct payment *p,
// TODO(eduardo): this includes pending HTLC of previous
// payments!
/* We know min and max liquidity exactly now! */
chan_extra_set_liquidity(chan_extra_map, scidd, max);
if (!chan_extra_set_liquidity(tmpctx, chan_extra_map, scidd, max,
&errmsg)) {
plugin_err(pay_plugin->plugin,
"chan_extra_set_liquidity failed: %s", errmsg);
}
}
/* Forget ALL channels information by a fraction of the capacity. */
void uncertainty_network_relax_fraction(
struct chan_extra_map* chan_extra_map,
double fraction)
void uncertainty_network_relax_fraction(struct chan_extra_map *chan_extra_map,
double fraction)
{
struct chan_extra_map_iter it;
for(struct chan_extra *ce=chan_extra_map_first(chan_extra_map,&it);
ce;
ce=chan_extra_map_next(chan_extra_map,&it))
{
chan_extra_relax_fraction(ce,fraction);
char *fail;
for (struct chan_extra *ce = chan_extra_map_first(chan_extra_map, &it);
ce; ce = chan_extra_map_next(chan_extra_map, &it)) {
if (!chan_extra_relax_fraction(tmpctx, ce, fraction, &fail)) {
plugin_err(pay_plugin->plugin,
"chan_extra_relax_fraction failed for "
"channel %s: %s",
type_to_string(tmpctx,
struct short_channel_id,
&ce->scid),
fail);
}
}
}