MCPcopy Create free account
hub / github.com/ElementsProject/lightning / substract_flow

Function substract_flow

plugins/askrene/child/mcf.c:712–769  ·  view source on GitHub ↗

Given a path from a node with negative balance to a node with positive * balance, compute the bigest flow and substract it from the nodes balance and * the channels allocation. */

Source from the content-addressed store, hash-verified

710 * balance, compute the bigest flow and substract it from the nodes balance and
711 * the channels allocation. */
712static struct flow *substract_flow(const tal_t *ctx,
713 const struct pay_parameters *params,
714 const struct node source,
715 const struct node sink,
716 s64 *balance, struct chan_flow *chan_flow,
717 const u32 *prev_idx, const int *prev_dir,
718 const struct gossmap_chan *const *prev_chan)
719{
720 const struct gossmap *gossmap = params->rq->gossmap;
721 assert(balance[source.idx] < 0);
722 assert(balance[sink.idx] > 0);
723 s64 delta = -balance[source.idx];
724 size_t length = 0;
725 delta = MIN(delta, balance[sink.idx]);
726
727 /* We can only walk backwards, now get me the legth of the path and the
728 * max flow we can send through this route. */
729 for (u32 cur_idx = sink.idx; cur_idx != source.idx;
730 cur_idx = prev_idx[cur_idx]) {
731 assert(cur_idx != INVALID_INDEX);
732 const int dir = prev_dir[cur_idx];
733 const struct gossmap_chan *const chan = prev_chan[cur_idx];
734
735 /* we could optimize here by caching the idx of the channels in
736 * the path, but the bottleneck of the algorithm is the MCF
737 * computation not here. */
738 const u32 chan_idx = gossmap_chan_idx(gossmap, chan);
739
740 delta = MIN(delta, chan_flow[chan_idx].half[dir]);
741 length++;
742 }
743
744 struct flow *f = tal(ctx, struct flow);
745 f->path = tal_arr(f, const struct gossmap_chan *, length);
746 f->dirs = tal_arr(f, int, length);
747
748 /* Walk again and substract the flow value (delta). */
749 assert(delta > 0);
750 balance[source.idx] += delta;
751 balance[sink.idx] -= delta;
752 for (u32 cur_idx = sink.idx; cur_idx != source.idx;
753 cur_idx = prev_idx[cur_idx]) {
754 const int dir = prev_dir[cur_idx];
755 const struct gossmap_chan *const chan = prev_chan[cur_idx];
756 const u32 chan_idx = gossmap_chan_idx(gossmap, chan);
757
758 length--;
759 /* f->path and f->dirs contain the channels in the path in the
760 * correct order. */
761 f->path[length] = chan;
762 f->dirs[length] = dir;
763
764 chan_flow[chan_idx].half[dir] -= delta;
765 }
766 if (!amount_msat_mul(&f->delivers, params->accuracy, delta))
767 abort();
768 return f;
769}

Callers 1

get_flow_pathsFunction · 0.85

Calls 3

gossmap_chan_idxFunction · 0.85
amount_msat_mulFunction · 0.85
abortFunction · 0.85

Tested by

no test coverage detected