routing: Refactor get_route into its own method

The JSON-RPC call `getroute` and the functionality to compute the
actual route have been split so that we can reuse it independently of
the JSON-interface. Since this is now a routing-only method I also
moved it into `routing.[ch]` instead of `pay.c`.
This commit is contained in:
Christian Decker 2017-03-15 12:44:01 +01:00 committed by Rusty Russell
parent 9273b615ab
commit 73e65cac4d
3 changed files with 75 additions and 59 deletions

View File

@ -201,17 +201,11 @@ static void json_getroute(struct command *cmd,
const char *buffer, const jsmntok_t *params)
{
struct pubkey id;
struct pubkey *first;
jsmntok_t *idtok, *msatoshitok, *riskfactortok;
struct json_result *response;
int i;
size_t i;
u64 msatoshi;
s64 fee;
double riskfactor;
struct node_connection **route;
struct peer *peer;
u64 *amounts, total_amount;
unsigned int total_delay, *delays;
if (!json_get_params(buffer, params,
"id", &idtok,
@ -242,45 +236,19 @@ static void json_getroute(struct command *cmd,
return;
}
first = find_route(cmd, cmd->dstate->rstate, &cmd->dstate->id, &id, msatoshi,
riskfactor, &fee, &route);
if (first)
peer = find_peer(cmd->dstate, first);
if (!first || !peer) {
struct route_hop *hops = get_route(cmd, cmd->dstate->rstate, &cmd->dstate->id, &id, msatoshi, riskfactor);
if (!hops) {
command_fail(cmd, "no route found");
return;
}
/* Fees, delays need to be calculated backwards along route. */
amounts = tal_arr(cmd, u64, tal_count(route)+1);
delays = tal_arr(cmd, unsigned int, tal_count(route)+1);
total_amount = msatoshi;
total_delay = 0;
for (i = tal_count(route) - 1; i >= 0; i--) {
amounts[i+1] = total_amount;
total_amount += connection_fee(route[i], total_amount);
total_delay += route[i]->delay;
if (total_delay < route[i]->min_blocks)
total_delay = route[i]->min_blocks;
delays[i+1] = total_delay;
}
/* We don't charge ourselves any fees. */
amounts[0] = total_amount;
/* We do require delay though. */
total_delay += peer->nc->delay;
if (total_delay < peer->nc->min_blocks)
total_delay = peer->nc->min_blocks;
delays[0] = total_delay;
response = new_json_result(cmd);
json_object_start(response, NULL);
json_array_start(response, "route");
json_add_route(response, peer->id, amounts[0], delays[0]);
for (i = 0; i < tal_count(route); i++)
for (i = 0; i < tal_count(hops); i++)
json_add_route(response,
&route[i]->dst->id, amounts[i+1], delays[i+1]);
&hops[i].nodeid, hops[i].amount, hops[i].delay);
json_array_end(response);
json_object_end(response);
command_success(cmd, response);

View File

@ -356,18 +356,14 @@ static void bfg_one_edge(struct node *node, size_t edgenum, double riskfactor)
}
}
struct pubkey *find_route(const tal_t *ctx,
struct routing_state *rstate,
const struct pubkey *from,
const struct pubkey *to,
u64 msatoshi,
double riskfactor,
s64 *fee,
struct node_connection ***route)
struct node_connection *
find_route(const tal_t *ctx, struct routing_state *rstate,
const struct pubkey *from, const struct pubkey *to, u64 msatoshi,
double riskfactor, s64 *fee, struct node_connection ***route)
{
struct node *n, *src, *dst;
struct node_map_iter it;
struct pubkey *first;
struct node_connection *first_conn;
int runs, i, best;
/* Note: we map backwards, since we know the amount of satoshi we want
@ -434,11 +430,10 @@ struct pubkey *find_route(const tal_t *ctx,
/* Save route from *next* hop (we return first hop as peer).
* Note that we take our own fees into account for routing, even
* though we don't pay them: it presumably effects preference. */
first_conn = dst->bfg[best].prev;
dst = dst->bfg[best].prev->dst;
best--;
first = &dst->id;
*fee = dst->bfg[best].total - msatoshi;
*route = tal_arr(ctx, struct node_connection *, best);
for (i = 0, n = dst;
@ -450,7 +445,7 @@ struct pubkey *find_route(const tal_t *ctx,
msatoshi += *fee;
log_info(rstate->base_log, "find_route:");
log_add_struct(rstate->base_log, "via %s", struct pubkey, first);
log_add_struct(rstate->base_log, "via %s", struct pubkey, &first_conn->dst->id);
/* If there are intermidiaries, dump them, and total fees. */
if (best != 0) {
for (i = 0; i < best; i++) {
@ -465,7 +460,7 @@ struct pubkey *find_route(const tal_t *ctx,
log_add(rstate->base_log, "=%"PRIi64"(%+"PRIi64")",
(*route)[best-1]->dst->bfg[best-1].total, *fee);
}
return first;
return first_conn;
}
static bool get_slash_u32(const char **arg, u32 *v)
@ -843,3 +838,48 @@ void handle_node_announcement(
node->node_announcement = tal_steal(node, serialized);
tal_free(tmpctx);
}
struct route_hop *get_route(tal_t *ctx, struct routing_state *rstate,
const struct pubkey *source,
const struct pubkey *destination,
const u32 msatoshi, double riskfactor)
{
struct node_connection **route;
u64 total_amount;
unsigned int total_delay;
s64 fee;
struct route_hop *hops;
int i;
struct node_connection *first_conn;
first_conn = find_route(ctx, rstate, source, destination, msatoshi,
riskfactor, &fee, &route);
if (!first_conn) {
return NULL;
}
/* Fees, delays need to be calculated backwards along route. */
hops = tal_arr(ctx, struct route_hop, tal_count(route) + 1);
total_amount = msatoshi;
total_delay = 0;
for (i = tal_count(route) - 1; i >= 0; i--) {
hops[i + 1].nodeid = route[i]->dst->id;
hops[i + 1].amount = total_amount;
total_amount += connection_fee(route[i], total_amount);
total_delay += route[i]->delay;
if (total_delay < route[i]->min_blocks)
total_delay = route[i]->min_blocks;
hops[i + 1].delay = total_delay;
}
/* Backfill the first hop manually */
hops[0].nodeid = first_conn->dst->id;
/* We don't charge ourselves any fees. */
hops[0].amount = total_amount;
/* We do require delay though. */
total_delay += first_conn->delay;
hops[0].delay = total_delay;
return hops;
}

View File

@ -88,6 +88,12 @@ struct routing_state {
struct broadcast_state *broadcasts;
};
struct route_hop {
struct pubkey nodeid;
u32 amount;
u32 delay;
};
//FIXME(cdecker) The log will have to be replaced for the new subdaemon, keeping for now to keep changes small.
struct routing_state *new_routing_state(const tal_t *ctx, struct log *base_log);
@ -139,14 +145,10 @@ struct node_connection *get_connection_by_scid(const struct routing_state *rstat
void remove_connection(struct routing_state *rstate,
const struct pubkey *src, const struct pubkey *dst);
struct pubkey *find_route(const tal_t *ctx,
struct routing_state *rstate,
const struct pubkey *from,
const struct pubkey *to,
u64 msatoshi,
double riskfactor,
s64 *fee,
struct node_connection ***route);
struct node_connection *
find_route(const tal_t *ctx, struct routing_state *rstate,
const struct pubkey *from, const struct pubkey *to, u64 msatoshi,
double riskfactor, s64 *fee, struct node_connection ***route);
struct node_map *empty_node_map(const tal_t *ctx);
@ -167,4 +169,10 @@ void handle_channel_announcement(struct routing_state *rstate, const u8 *announc
void handle_channel_update(struct routing_state *rstate, const u8 *update, size_t len);
void handle_node_announcement(struct routing_state *rstate, const u8 *node, size_t len);
/* Compute a route to a destination, for a given amount and riskfactor. */
struct route_hop *get_route(tal_t *ctx, struct routing_state *rstate,
const struct pubkey *source,
const struct pubkey *destination,
const u32 msatoshi, double riskfactor);
#endif /* LIGHTNING_DAEMON_ROUTING_H */