mirror of
https://github.com/aljazceru/lightning.git
synced 2025-12-20 07:34:24 +01:00
payalgo: Randomize paths as long as we respect maxfeepercent.
This commit is contained in:
@@ -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 */
|
||||||
|
|||||||
Reference in New Issue
Block a user