Skip to content

Commit cceed8e

Browse files
committed
topology: in deterministic mode, only return one best candidate for listincoming.
This ensures that bolt11/bolt12 selection of routehints/blinded paths is always the same. Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
1 parent 65388cf commit cceed8e

File tree

1 file changed

+36
-0
lines changed

1 file changed

+36
-0
lines changed

plugins/topology.c

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
#include <common/json_param.h>
99
#include <common/json_stream.h>
1010
#include <common/memleak.h>
11+
#include <common/randbytes.h>
1112
#include <common/route.h>
1213
#include <errno.h>
1314
#include <inttypes.h>
@@ -459,6 +460,33 @@ static struct amount_msat peer_capacity(const struct gossmap *gossmap,
459460
return capacity;
460461
}
461462

463+
/* For deterministic results with bolt12/11 routes, we only return a
464+
* single candidate: choose the one with most capacity */
465+
static size_t best_candidate(const struct gossmap *gossmap,
466+
const struct gossmap_node *me)
467+
{
468+
struct amount_msat best_cap = AMOUNT_MSAT(0);
469+
size_t best_num = 0;
470+
for (size_t i = 0; i < me->num_chans; i++) {
471+
int dir;
472+
struct gossmap_chan *ourchan;
473+
struct amount_msat cap;
474+
struct gossmap_node *peer;
475+
476+
ourchan = gossmap_nth_chan(gossmap, me, i, &dir);
477+
if (ourchan->cupdate_off[!dir] == 0)
478+
continue;
479+
480+
peer = gossmap_nth_node(gossmap, ourchan, !dir);
481+
cap = peer_capacity(gossmap, me, peer, ourchan);
482+
if (amount_msat_greater(cap, best_cap)) {
483+
best_num = i;
484+
best_cap = cap;
485+
}
486+
}
487+
return best_num;
488+
}
489+
462490
static struct command_result *
463491
listpeerchannels_listincoming_done(struct command *cmd,
464492
const char *method,
@@ -470,6 +498,7 @@ listpeerchannels_listincoming_done(struct command *cmd,
470498
struct gossmap_node *me;
471499
struct gossmap *gossmap;
472500
struct gossmap_localmods *mods;
501+
size_t deterministic_candidate = 0;
473502

474503
/* Get local knowledge */
475504
mods = gossmods_from_listpeerchannels(tmpctx, &local_id,
@@ -487,6 +516,9 @@ listpeerchannels_listincoming_done(struct command *cmd,
487516
if (!me)
488517
goto done;
489518

519+
if (randbytes_overridden())
520+
deterministic_candidate = best_candidate(gossmap, me);
521+
490522
for (size_t i = 0; i < me->num_chans; i++) {
491523
struct node_id peer_id;
492524
int dir;
@@ -499,6 +531,10 @@ listpeerchannels_listincoming_done(struct command *cmd,
499531
/* Entirely missing? Ignore. */
500532
if (ourchan->cupdate_off[!dir] == 0)
501533
continue;
534+
535+
if (randbytes_overridden() && i != deterministic_candidate)
536+
continue;
537+
502538
/* We used to ignore if the peer said it was disabled,
503539
* but we have a report of LND telling us our unannounced
504540
* channel is disabled, so we still use them. */

0 commit comments

Comments
 (0)