Search in the network a path of positive flow until we reach a node with * positive balance (returns a node idx with positive balance) * or we discover a cycle (returns a node idx with 0 balance). * */
| 636 | * or we discover a cycle (returns a node idx with 0 balance). |
| 637 | * */ |
| 638 | static struct node find_path_or_cycle( |
| 639 | const tal_t *working_ctx, |
| 640 | const struct route_query *rq, |
| 641 | const struct chan_flow *chan_flow, |
| 642 | const struct node source, |
| 643 | const s64 *balance, |
| 644 | |
| 645 | const struct gossmap_chan **prev_chan, |
| 646 | int *prev_dir, |
| 647 | u32 *prev_idx) |
| 648 | { |
| 649 | const struct gossmap *gossmap = rq->gossmap; |
| 650 | const size_t max_num_nodes = gossmap_max_node_idx(gossmap); |
| 651 | bitmap *visited = |
| 652 | tal_arrz(working_ctx, bitmap, BITMAP_NWORDS(max_num_nodes)); |
| 653 | u32 final_idx = source.idx; |
| 654 | bitmap_set_bit(visited, final_idx); |
| 655 | |
| 656 | /* It is guaranteed to halt, because we either find a node with |
| 657 | * balance[]>0 or we hit a node twice and we stop. */ |
| 658 | while (balance[final_idx] <= 0) { |
| 659 | u32 updated_idx = INVALID_INDEX; |
| 660 | struct gossmap_node *cur = |
| 661 | gossmap_node_byidx(gossmap, final_idx); |
| 662 | |
| 663 | for (size_t i = 0; i < cur->num_chans; ++i) { |
| 664 | int dir; |
| 665 | const struct gossmap_chan *c = |
| 666 | gossmap_nth_chan(gossmap, cur, i, &dir); |
| 667 | |
| 668 | if (!channel_is_available(rq, c, dir)) |
| 669 | continue; |
| 670 | |
| 671 | const u32 c_idx = gossmap_chan_idx(gossmap, c); |
| 672 | |
| 673 | /* follow the flow */ |
| 674 | if (chan_flow[c_idx].half[dir] > 0) { |
| 675 | const struct gossmap_node *n = |
| 676 | gossmap_nth_node(gossmap, c, !dir); |
| 677 | u32 next_idx = gossmap_node_idx(gossmap, n); |
| 678 | |
| 679 | prev_dir[next_idx] = dir; |
| 680 | prev_chan[next_idx] = c; |
| 681 | prev_idx[next_idx] = final_idx; |
| 682 | |
| 683 | updated_idx = next_idx; |
| 684 | break; |
| 685 | } |
| 686 | } |
| 687 | |
| 688 | assert(updated_idx != INVALID_INDEX); |
| 689 | assert(updated_idx != final_idx); |
| 690 | final_idx = updated_idx; |
| 691 | |
| 692 | if (bitmap_test_bit(visited, updated_idx)) { |
| 693 | /* We have seen this node before, we've found a cycle. |
| 694 | */ |
| 695 | assert(balance[updated_idx] <= 0); |
no test coverage detected