mirror of
https://github.com/ElementsProject/lightning.git
synced 2024-11-19 18:11:28 +01:00
uniform error handling pattern for flow.c
This commit is contained in:
parent
af3bcddc1f
commit
1f6772160f
File diff suppressed because it is too large
Load Diff
@ -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 */
|
||||
|
@ -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 ||
|
||||
|
@ -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]));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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,
|
||||
|
@ -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,
|
||||
|
@ -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;
|
||||
|
@ -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 */
|
||||
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user