From 6767434ea989902d7b62bfa5db44d57469bae629 Mon Sep 17 00:00:00 2001 From: ZmnSCPxj Date: Fri, 23 Feb 2018 00:00:00 +0000 Subject: [PATCH] routing: Use siphash24 for route randomization Primary idea by @rustyrussell --- gossipd/gossip.c | 16 ++++++++++--- gossipd/routing.c | 36 ++++++++++------------------- gossipd/routing.h | 4 +++- gossipd/test/run-bench-find_route.c | 4 +++- lightningd/gossip_control.c | 4 ++-- lightningd/payalgo.c | 4 ++-- 6 files changed, 35 insertions(+), 33 deletions(-) diff --git a/gossipd/gossip.c b/gossipd/gossip.c index fb53279b5..26779fb0f 100644 --- a/gossipd/gossip.c +++ b/gossipd/gossip.c @@ -2,6 +2,7 @@ #include #include #include +#include #include #include #include @@ -1048,19 +1049,28 @@ static struct io_plan *getroute_req(struct io_conn *conn, struct daemon *daemon, u8 *out; struct route_hop *hops; double fuzz; - u8 *seed; + u8 *rawseed; + struct siphash_seed seed; + size_t seedbytes; fromwire_gossip_getroute_request(tmpctx, msg, &source, &destination, &msatoshi, &riskfactor, &final_cltv, - &fuzz, &seed); + &fuzz, &rawseed); status_trace("Trying to find a route from %s to %s for %d msatoshi", pubkey_to_hexstr(tmpctx, &source), pubkey_to_hexstr(tmpctx, &destination), msatoshi); + /* Initialize siphash */ + memset(&seed, 0, sizeof(seed)); + seedbytes = + (tal_len(rawseed) > sizeof(seed)) ? sizeof(seed) : + /*otherwise*/ tal_len(rawseed) ; + memcpy(&seed, rawseed, seedbytes); + hops = get_route(tmpctx, daemon->rstate, &source, &destination, msatoshi, 1, final_cltv, - fuzz, seed); + fuzz, &seed); out = towire_gossip_getroute_reply(msg, hops); tal_free(tmpctx); diff --git a/gossipd/routing.c b/gossipd/routing.c index 5c54c8515..9007c102d 100644 --- a/gossipd/routing.c +++ b/gossipd/routing.c @@ -3,9 +3,7 @@ #include #include #include -#include #include -#include #include #include #include @@ -333,28 +331,22 @@ static u64 risk_fee(u64 amount, u32 delay, double riskfactor) /* We track totals, rather than costs. That's because the fee depends * on the current amount passing through. */ static void bfg_one_edge(struct node *node, size_t edgenum, double riskfactor, - double fuzz, const struct isaac64_ctx *baserng) + double fuzz, const struct siphash_seed *base_seed) { struct node_connection *c = node->in[edgenum]; size_t h; - struct isaac64_ctx myrng; double fee_scale = 1.0; - u8 *scid; if (fuzz != 0.0) { - /* Copy RNG state */ - myrng = *baserng; - - /* Provide the channel short ID, as additional - * entropy. */ - scid = tal_arr(NULL, u8, 0); - towire_short_channel_id(&scid, &c->short_channel_id); - isaac64_reseed(&myrng, - (const unsigned char *) scid, tal_len(scid)); - tal_free(scid); + u64 scid = short_channel_id_to_uint(&c->short_channel_id); + u64 h = siphash24(base_seed, &scid, sizeof(scid)); /* Scale fees for this channel */ - fee_scale = 1.0 + fuzz * isaac64_next_signed_double(&myrng); + /* rand = (h / UINT64_MAX) random number between 0.0 -> 1.0 + * 2*fuzz*rand random number between 0.0 -> 2*fuzz + * 2*fuzz*rand - fuzz random number between -fuzz -> +fuzz + */ + fee_scale = 1.0 + (2.0 * fuzz * h / UINT64_MAX) - fuzz; } assert(c->dst == node); @@ -402,7 +394,7 @@ static 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, - double fuzz, struct isaac64_ctx *baserng, + double fuzz, const struct siphash_seed *base_seed, u64 *fee, struct node_connection ***route) { struct node *n, *src, *dst; @@ -464,7 +456,7 @@ find_route(const tal_t *ctx, struct routing_state *rstate, continue; } bfg_one_edge(n, i, riskfactor, - fuzz, baserng); + fuzz, base_seed); SUPERVERBOSE("...done"); } } @@ -1143,7 +1135,7 @@ struct route_hop *get_route(tal_t *ctx, struct routing_state *rstate, const struct pubkey *destination, const u32 msatoshi, double riskfactor, u32 final_cltv, - double fuzz, u8 *seed) + double fuzz, const struct siphash_seed *base_seed) { struct node_connection **route; u64 total_amount; @@ -1152,14 +1144,10 @@ struct route_hop *get_route(tal_t *ctx, struct routing_state *rstate, struct route_hop *hops; int i; struct node_connection *first_conn; - isaac64_ctx baserng; - - /* Load base RNG */ - isaac64_init(&baserng, (const unsigned char*) seed, tal_count(seed)); first_conn = find_route(ctx, rstate, source, destination, msatoshi, riskfactor / BLOCKS_PER_YEAR / 10000, - fuzz, &baserng, + fuzz, base_seed, &fee, &route); if (!first_conn) { diff --git a/gossipd/routing.h b/gossipd/routing.h index 1afd71b15..ab713a3e8 100644 --- a/gossipd/routing.h +++ b/gossipd/routing.h @@ -2,6 +2,7 @@ #define LIGHTNING_LIGHTNINGD_GOSSIP_ROUTING_H #include "config.h" #include +#include #include #include #include @@ -187,7 +188,8 @@ struct route_hop *get_route(tal_t *ctx, struct routing_state *rstate, const struct pubkey *destination, const u32 msatoshi, double riskfactor, u32 final_cltv, - double fuzz, u8 *seed); + double fuzz, + const struct siphash_seed *base_seed); /* Disable channel(s) based on the given routing failure. */ void routing_failure(struct routing_state *rstate, const struct pubkey *erring_node, diff --git a/gossipd/test/run-bench-find_route.c b/gossipd/test/run-bench-find_route.c index 8b9667f1a..c091e7eff 100644 --- a/gossipd/test/run-bench-find_route.c +++ b/gossipd/test/run-bench-find_route.c @@ -177,6 +177,7 @@ int main(int argc, char *argv[]) struct pubkey me = nodeid(0); bool perfme = false; const double riskfactor = 0.01 / BLOCKS_PER_YEAR / 10000; + struct siphash_seed base_seed; secp256k1_ctx = secp256k1_context_create(SECP256K1_CONTEXT_VERIFY | SECP256K1_CONTEXT_SIGN); @@ -194,6 +195,7 @@ int main(int argc, char *argv[]) if (argc > 3) opt_usage_and_exit("[num_nodes [num_runs]]"); + memset(&base_seed, 0, sizeof(base_seed)); for (size_t i = 0; i < num_nodes; i++) populate_random_node(rstate, i); @@ -212,7 +214,7 @@ int main(int argc, char *argv[]) nc = find_route(ctx, rstate, &from, &to, pseudorand(100000), riskfactor, - 0.0, NULL, + 0.75, &base_seed, &fee, &route); num_success += (nc != NULL); tal_free(route); diff --git a/lightningd/gossip_control.c b/lightningd/gossip_control.c index 1436fb689..787d6b2bd 100644 --- a/lightningd/gossip_control.c +++ b/lightningd/gossip_control.c @@ -5,9 +5,9 @@ #include "peer_control.h" #include "subd.h" #include +#include #include #include -#include #include #include #include @@ -308,7 +308,7 @@ static void json_getroute(struct command *cmd, const char *buffer, const jsmntok unsigned cltv = 9; double riskfactor; double fuzz = 5.0; - u8 *seed = tal_arrz(cmd, u8, ISAAC64_SEED_SZ_MAX); + u8 *seed = tal_arrz(cmd, u8, sizeof(struct siphash_seed)); if (!json_get_params(cmd, buffer, params, "id", &idtok, diff --git a/lightningd/payalgo.c b/lightningd/payalgo.c index 98ce3ba09..0ac9949af 100644 --- a/lightningd/payalgo.c +++ b/lightningd/payalgo.c @@ -1,6 +1,6 @@ #include "pay.h" #include "payalgo.h" -#include +#include #include #include #include @@ -243,7 +243,7 @@ static bool json_pay_try(struct pay *pay) pay->try_parent = tal(pay, char); /* Generate random seed */ - seed = tal_arr(pay->try_parent, u8, ISAAC64_SEED_SZ_MAX); + seed = tal_arr(pay->try_parent, u8, sizeof(struct siphash_seed)); randombytes_buf(seed, tal_len(seed)); ++pay->getroute_tries;