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. */
| 710 | * balance, compute the bigest flow and substract it from the nodes balance and |
| 711 | * the channels allocation. */ |
| 712 | static 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 | } |
no test coverage detected