mirror of
https://github.com/ElementsProject/lightning.git
synced 2025-01-18 05:12:45 +01:00
routing: Use siphash24 for route randomization
Primary idea by @rustyrussell
This commit is contained in:
parent
1cf32f9f05
commit
6767434ea9
@ -2,6 +2,7 @@
|
|||||||
#include <ccan/cast/cast.h>
|
#include <ccan/cast/cast.h>
|
||||||
#include <ccan/container_of/container_of.h>
|
#include <ccan/container_of/container_of.h>
|
||||||
#include <ccan/crypto/hkdf_sha256/hkdf_sha256.h>
|
#include <ccan/crypto/hkdf_sha256/hkdf_sha256.h>
|
||||||
|
#include <ccan/crypto/siphash24/siphash24.h>
|
||||||
#include <ccan/endian/endian.h>
|
#include <ccan/endian/endian.h>
|
||||||
#include <ccan/fdpass/fdpass.h>
|
#include <ccan/fdpass/fdpass.h>
|
||||||
#include <ccan/io/fdpass/fdpass.h>
|
#include <ccan/io/fdpass/fdpass.h>
|
||||||
@ -1048,19 +1049,28 @@ static struct io_plan *getroute_req(struct io_conn *conn, struct daemon *daemon,
|
|||||||
u8 *out;
|
u8 *out;
|
||||||
struct route_hop *hops;
|
struct route_hop *hops;
|
||||||
double fuzz;
|
double fuzz;
|
||||||
u8 *seed;
|
u8 *rawseed;
|
||||||
|
struct siphash_seed seed;
|
||||||
|
size_t seedbytes;
|
||||||
|
|
||||||
fromwire_gossip_getroute_request(tmpctx, msg,
|
fromwire_gossip_getroute_request(tmpctx, msg,
|
||||||
&source, &destination,
|
&source, &destination,
|
||||||
&msatoshi, &riskfactor, &final_cltv,
|
&msatoshi, &riskfactor, &final_cltv,
|
||||||
&fuzz, &seed);
|
&fuzz, &rawseed);
|
||||||
status_trace("Trying to find a route from %s to %s for %d msatoshi",
|
status_trace("Trying to find a route from %s to %s for %d msatoshi",
|
||||||
pubkey_to_hexstr(tmpctx, &source),
|
pubkey_to_hexstr(tmpctx, &source),
|
||||||
pubkey_to_hexstr(tmpctx, &destination), msatoshi);
|
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,
|
hops = get_route(tmpctx, daemon->rstate, &source, &destination,
|
||||||
msatoshi, 1, final_cltv,
|
msatoshi, 1, final_cltv,
|
||||||
fuzz, seed);
|
fuzz, &seed);
|
||||||
|
|
||||||
out = towire_gossip_getroute_reply(msg, hops);
|
out = towire_gossip_getroute_reply(msg, hops);
|
||||||
tal_free(tmpctx);
|
tal_free(tmpctx);
|
||||||
|
@ -3,9 +3,7 @@
|
|||||||
#include <bitcoin/block.h>
|
#include <bitcoin/block.h>
|
||||||
#include <bitcoin/script.h>
|
#include <bitcoin/script.h>
|
||||||
#include <ccan/array_size/array_size.h>
|
#include <ccan/array_size/array_size.h>
|
||||||
#include <ccan/crypto/siphash24/siphash24.h>
|
|
||||||
#include <ccan/endian/endian.h>
|
#include <ccan/endian/endian.h>
|
||||||
#include <ccan/isaac/isaac64.h>
|
|
||||||
#include <ccan/structeq/structeq.h>
|
#include <ccan/structeq/structeq.h>
|
||||||
#include <ccan/tal/str/str.h>
|
#include <ccan/tal/str/str.h>
|
||||||
#include <common/features.h>
|
#include <common/features.h>
|
||||||
@ -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
|
/* We track totals, rather than costs. That's because the fee depends
|
||||||
* on the current amount passing through. */
|
* on the current amount passing through. */
|
||||||
static void bfg_one_edge(struct node *node, size_t edgenum, double riskfactor,
|
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];
|
struct node_connection *c = node->in[edgenum];
|
||||||
size_t h;
|
size_t h;
|
||||||
struct isaac64_ctx myrng;
|
|
||||||
double fee_scale = 1.0;
|
double fee_scale = 1.0;
|
||||||
u8 *scid;
|
|
||||||
|
|
||||||
if (fuzz != 0.0) {
|
if (fuzz != 0.0) {
|
||||||
/* Copy RNG state */
|
u64 scid = short_channel_id_to_uint(&c->short_channel_id);
|
||||||
myrng = *baserng;
|
u64 h = siphash24(base_seed, &scid, sizeof(scid));
|
||||||
|
|
||||||
/* 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);
|
|
||||||
|
|
||||||
/* Scale fees for this channel */
|
/* 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);
|
assert(c->dst == node);
|
||||||
@ -402,7 +394,7 @@ static struct node_connection *
|
|||||||
find_route(const tal_t *ctx, struct routing_state *rstate,
|
find_route(const tal_t *ctx, struct routing_state *rstate,
|
||||||
const struct pubkey *from, const struct pubkey *to, u64 msatoshi,
|
const struct pubkey *from, const struct pubkey *to, u64 msatoshi,
|
||||||
double riskfactor,
|
double riskfactor,
|
||||||
double fuzz, struct isaac64_ctx *baserng,
|
double fuzz, const struct siphash_seed *base_seed,
|
||||||
u64 *fee, struct node_connection ***route)
|
u64 *fee, struct node_connection ***route)
|
||||||
{
|
{
|
||||||
struct node *n, *src, *dst;
|
struct node *n, *src, *dst;
|
||||||
@ -464,7 +456,7 @@ find_route(const tal_t *ctx, struct routing_state *rstate,
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
bfg_one_edge(n, i, riskfactor,
|
bfg_one_edge(n, i, riskfactor,
|
||||||
fuzz, baserng);
|
fuzz, base_seed);
|
||||||
SUPERVERBOSE("...done");
|
SUPERVERBOSE("...done");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1143,7 +1135,7 @@ struct route_hop *get_route(tal_t *ctx, struct routing_state *rstate,
|
|||||||
const struct pubkey *destination,
|
const struct pubkey *destination,
|
||||||
const u32 msatoshi, double riskfactor,
|
const u32 msatoshi, double riskfactor,
|
||||||
u32 final_cltv,
|
u32 final_cltv,
|
||||||
double fuzz, u8 *seed)
|
double fuzz, const struct siphash_seed *base_seed)
|
||||||
{
|
{
|
||||||
struct node_connection **route;
|
struct node_connection **route;
|
||||||
u64 total_amount;
|
u64 total_amount;
|
||||||
@ -1152,14 +1144,10 @@ struct route_hop *get_route(tal_t *ctx, struct routing_state *rstate,
|
|||||||
struct route_hop *hops;
|
struct route_hop *hops;
|
||||||
int i;
|
int i;
|
||||||
struct node_connection *first_conn;
|
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,
|
first_conn = find_route(ctx, rstate, source, destination, msatoshi,
|
||||||
riskfactor / BLOCKS_PER_YEAR / 10000,
|
riskfactor / BLOCKS_PER_YEAR / 10000,
|
||||||
fuzz, &baserng,
|
fuzz, base_seed,
|
||||||
&fee, &route);
|
&fee, &route);
|
||||||
|
|
||||||
if (!first_conn) {
|
if (!first_conn) {
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
#define LIGHTNING_LIGHTNINGD_GOSSIP_ROUTING_H
|
#define LIGHTNING_LIGHTNINGD_GOSSIP_ROUTING_H
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
#include <bitcoin/pubkey.h>
|
#include <bitcoin/pubkey.h>
|
||||||
|
#include <ccan/crypto/siphash24/siphash24.h>
|
||||||
#include <ccan/htable/htable_type.h>
|
#include <ccan/htable/htable_type.h>
|
||||||
#include <ccan/time/time.h>
|
#include <ccan/time/time.h>
|
||||||
#include <gossipd/broadcast.h>
|
#include <gossipd/broadcast.h>
|
||||||
@ -187,7 +188,8 @@ struct route_hop *get_route(tal_t *ctx, struct routing_state *rstate,
|
|||||||
const struct pubkey *destination,
|
const struct pubkey *destination,
|
||||||
const u32 msatoshi, double riskfactor,
|
const u32 msatoshi, double riskfactor,
|
||||||
u32 final_cltv,
|
u32 final_cltv,
|
||||||
double fuzz, u8 *seed);
|
double fuzz,
|
||||||
|
const struct siphash_seed *base_seed);
|
||||||
/* Disable channel(s) based on the given routing failure. */
|
/* Disable channel(s) based on the given routing failure. */
|
||||||
void routing_failure(struct routing_state *rstate,
|
void routing_failure(struct routing_state *rstate,
|
||||||
const struct pubkey *erring_node,
|
const struct pubkey *erring_node,
|
||||||
|
@ -177,6 +177,7 @@ int main(int argc, char *argv[])
|
|||||||
struct pubkey me = nodeid(0);
|
struct pubkey me = nodeid(0);
|
||||||
bool perfme = false;
|
bool perfme = false;
|
||||||
const double riskfactor = 0.01 / BLOCKS_PER_YEAR / 10000;
|
const double riskfactor = 0.01 / BLOCKS_PER_YEAR / 10000;
|
||||||
|
struct siphash_seed base_seed;
|
||||||
|
|
||||||
secp256k1_ctx = secp256k1_context_create(SECP256K1_CONTEXT_VERIFY
|
secp256k1_ctx = secp256k1_context_create(SECP256K1_CONTEXT_VERIFY
|
||||||
| SECP256K1_CONTEXT_SIGN);
|
| SECP256K1_CONTEXT_SIGN);
|
||||||
@ -194,6 +195,7 @@ int main(int argc, char *argv[])
|
|||||||
if (argc > 3)
|
if (argc > 3)
|
||||||
opt_usage_and_exit("[num_nodes [num_runs]]");
|
opt_usage_and_exit("[num_nodes [num_runs]]");
|
||||||
|
|
||||||
|
memset(&base_seed, 0, sizeof(base_seed));
|
||||||
for (size_t i = 0; i < num_nodes; i++)
|
for (size_t i = 0; i < num_nodes; i++)
|
||||||
populate_random_node(rstate, i);
|
populate_random_node(rstate, i);
|
||||||
|
|
||||||
@ -212,7 +214,7 @@ int main(int argc, char *argv[])
|
|||||||
nc = find_route(ctx, rstate, &from, &to,
|
nc = find_route(ctx, rstate, &from, &to,
|
||||||
pseudorand(100000),
|
pseudorand(100000),
|
||||||
riskfactor,
|
riskfactor,
|
||||||
0.0, NULL,
|
0.75, &base_seed,
|
||||||
&fee, &route);
|
&fee, &route);
|
||||||
num_success += (nc != NULL);
|
num_success += (nc != NULL);
|
||||||
tal_free(route);
|
tal_free(route);
|
||||||
|
@ -5,9 +5,9 @@
|
|||||||
#include "peer_control.h"
|
#include "peer_control.h"
|
||||||
#include "subd.h"
|
#include "subd.h"
|
||||||
#include <ccan/array_size/array_size.h>
|
#include <ccan/array_size/array_size.h>
|
||||||
|
#include <ccan/crypto/siphash24/siphash24.h>
|
||||||
#include <ccan/err/err.h>
|
#include <ccan/err/err.h>
|
||||||
#include <ccan/fdpass/fdpass.h>
|
#include <ccan/fdpass/fdpass.h>
|
||||||
#include <ccan/isaac/isaac64.h>
|
|
||||||
#include <ccan/take/take.h>
|
#include <ccan/take/take.h>
|
||||||
#include <ccan/tal/str/str.h>
|
#include <ccan/tal/str/str.h>
|
||||||
#include <common/features.h>
|
#include <common/features.h>
|
||||||
@ -308,7 +308,7 @@ static void json_getroute(struct command *cmd, const char *buffer, const jsmntok
|
|||||||
unsigned cltv = 9;
|
unsigned cltv = 9;
|
||||||
double riskfactor;
|
double riskfactor;
|
||||||
double fuzz = 5.0;
|
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,
|
if (!json_get_params(cmd, buffer, params,
|
||||||
"id", &idtok,
|
"id", &idtok,
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
#include "pay.h"
|
#include "pay.h"
|
||||||
#include "payalgo.h"
|
#include "payalgo.h"
|
||||||
#include <ccan/isaac/isaac64.h>
|
#include <ccan/crypto/siphash24/siphash24.h>
|
||||||
#include <ccan/tal/str/str.h>
|
#include <ccan/tal/str/str.h>
|
||||||
#include <ccan/time/time.h>
|
#include <ccan/time/time.h>
|
||||||
#include <common/bolt11.h>
|
#include <common/bolt11.h>
|
||||||
@ -243,7 +243,7 @@ static bool json_pay_try(struct pay *pay)
|
|||||||
pay->try_parent = tal(pay, char);
|
pay->try_parent = tal(pay, char);
|
||||||
|
|
||||||
/* Generate random seed */
|
/* 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));
|
randombytes_buf(seed, tal_len(seed));
|
||||||
|
|
||||||
++pay->getroute_tries;
|
++pay->getroute_tries;
|
||||||
|
Loading…
Reference in New Issue
Block a user