Browse Source

payalgo: Randomize paths as long as we respect maxfeepercent.

ppa-0.6.1
ZmnSCPxj 7 years ago
committed by Rusty Russell
parent
commit
61d0b50c54
  1. 50
      lightningd/payalgo.c

50
lightningd/payalgo.c

@ -1,5 +1,6 @@
#include "pay.h" #include "pay.h"
#include "payalgo.h" #include "payalgo.h"
#include <ccan/isaac/isaac64.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>
@ -9,6 +10,7 @@
#include <lightningd/jsonrpc_errors.h> #include <lightningd/jsonrpc_errors.h>
#include <lightningd/lightningd.h> #include <lightningd/lightningd.h>
#include <lightningd/subd.h> #include <lightningd/subd.h>
#include <sodium/randombytes.h>
struct pay { struct pay {
/* Parent command. */ /* Parent command. */
@ -25,8 +27,12 @@ struct pay {
double riskfactor; double riskfactor;
double maxfeepercent; double maxfeepercent;
/* Number of payment tries */ /* Number of getroute and sendpay tries */
unsigned int tries; unsigned int getroute_tries;
unsigned int sendpay_tries;
/* Current fuzz we pass into getroute. */
double fuzz;
/* Parent of the current pay attempt. This object is /* Parent of the current pay attempt. This object is
* freed, then allocated at the start of each pay * freed, then allocated at the start of each pay
@ -37,7 +43,8 @@ struct pay {
static void static void
json_pay_success(struct command *cmd, json_pay_success(struct command *cmd,
const struct preimage *payment_preimage, const struct preimage *payment_preimage,
unsigned int tries) unsigned int getroute_tries,
unsigned int sendpay_tries)
{ {
struct json_result *response; struct json_result *response;
@ -45,7 +52,8 @@ json_pay_success(struct command *cmd,
json_object_start(response, NULL); json_object_start(response, NULL);
json_add_hex(response, "preimage", json_add_hex(response, "preimage",
payment_preimage, sizeof(*payment_preimage)); payment_preimage, sizeof(*payment_preimage));
json_add_num(response, "tries", tries); json_add_num(response, "getroute_tries", getroute_tries);
json_add_num(response, "sendpay_tries", sendpay_tries);
json_object_end(response); json_object_end(response);
command_success(cmd, response); command_success(cmd, response);
} }
@ -126,7 +134,8 @@ static void json_pay_sendpay_resolve(const struct sendpay_result *r,
/* If we succeed, hurray */ /* If we succeed, hurray */
if (r->succeeded) { if (r->succeeded) {
json_pay_success(pay->cmd, &r->preimage, pay->tries); json_pay_success(pay->cmd, &r->preimage,
pay->getroute_tries, pay->sendpay_tries);
return; return;
} }
@ -149,6 +158,7 @@ static void json_pay_getroute_reply(struct subd *gossip UNUSED,
u64 msatoshi_sent; u64 msatoshi_sent;
u64 fee; u64 fee;
double feepercent; double feepercent;
bool fee_too_high;
struct json_result *data; struct json_result *data;
fromwire_gossip_getroute_reply(reply, reply, &route); fromwire_gossip_getroute_reply(reply, reply, &route);
@ -169,7 +179,9 @@ static void json_pay_getroute_reply(struct subd *gossip UNUSED,
* and thus losing precision in the below. Currently, OK, as, * and thus losing precision in the below. Currently, OK, as,
* payments are limited to 4294967295 msatoshi. */ * payments are limited to 4294967295 msatoshi. */
feepercent = ((double) fee) * 100.0 / ((double) pay->msatoshi); feepercent = ((double) fee) * 100.0 / ((double) pay->msatoshi);
if (feepercent > pay->maxfeepercent) { fee_too_high = (feepercent > pay->maxfeepercent);
/* compare fuzz to range */
if (fee_too_high && pay->fuzz < 0.01) {
data = new_json_result(pay); data = new_json_result(pay);
json_object_start(data, NULL); json_object_start(data, NULL);
json_add_u64(data, "fee", fee); json_add_u64(data, "fee", fee);
@ -188,6 +200,16 @@ static void json_pay_getroute_reply(struct subd *gossip UNUSED,
pay->maxfeepercent); pay->maxfeepercent);
return; return;
} }
if (fee_too_high) {
/* Retry with lower fuzz */
pay->fuzz -= 0.15;
if (pay->fuzz <= 0.0)
pay->fuzz = 0.0;
json_pay_try(pay);
return;
}
++pay->sendpay_tries;
send_payment(pay->try_parent, send_payment(pay->try_parent,
pay->cmd->ld, &pay->payment_hash, route, pay->cmd->ld, &pay->payment_hash, route,
@ -198,6 +220,7 @@ static void json_pay_getroute_reply(struct subd *gossip UNUSED,
* false if resolved now. */ * false if resolved now. */
static bool json_pay_try(struct pay *pay) static bool json_pay_try(struct pay *pay)
{ {
u8 *seed;
u8 *req; u8 *req;
struct command *cmd = pay->cmd; struct command *cmd = pay->cmd;
struct timeabs now = time_now(); struct timeabs now = time_now();
@ -215,11 +238,15 @@ static bool json_pay_try(struct pay *pay)
return false; return false;
} }
/* Clear previous sendpay. */ /* Clear previous try memory. */
pay->try_parent = tal_free(pay->try_parent); pay->try_parent = tal_free(pay->try_parent);
pay->try_parent = tal(pay, char); pay->try_parent = tal(pay, char);
++pay->tries; /* Generate random seed */
seed = tal_arr(pay->try_parent, u8, ISAAC64_SEED_SZ_MAX);
randombytes_buf(seed, tal_len(seed));
++pay->getroute_tries;
/* FIXME: use b11->routes */ /* FIXME: use b11->routes */
req = towire_gossip_getroute_request(pay->try_parent, req = towire_gossip_getroute_request(pay->try_parent,
@ -228,7 +255,8 @@ static bool json_pay_try(struct pay *pay)
pay->msatoshi, pay->msatoshi,
pay->riskfactor, pay->riskfactor,
pay->min_final_cltv_expiry, pay->min_final_cltv_expiry,
0, tal_arrz(pay->try_parent, u8, 8)); &pay->fuzz,
seed);
subd_req(pay->try_parent, cmd->ld->gossip, req, -1, 0, json_pay_getroute_reply, pay); subd_req(pay->try_parent, cmd->ld->gossip, req, -1, 0, json_pay_getroute_reply, pay);
return true; return true;
@ -326,7 +354,9 @@ static void json_pay(struct command *cmd,
} }
pay->maxfeepercent = maxfeepercent; pay->maxfeepercent = maxfeepercent;
pay->tries = 0; pay->getroute_tries = 0;
pay->sendpay_tries = 0;
pay->fuzz = 0.75;
pay->try_parent = NULL; pay->try_parent = NULL;
/* Initiate payment */ /* Initiate payment */

Loading…
Cancel
Save