pay: restore payment value randomization through shadow routing

When doing the random walk through the channel, we now add the fees
(both the base and the proportional one) for that channel in addition to
the cltv delta.

Changelog-Added: Payment amount fuzzing is restored, but through shadow routing.
This commit is contained in:
darosior 2019-11-04 15:57:07 +01:00 committed by Rusty Russell
parent 290b4d68b3
commit 5766231d98
3 changed files with 47 additions and 34 deletions

View File

@ -51,19 +51,19 @@ randomization\.
1: Route Randomization 1: Route Randomization
2: Shadow Route
Route randomization means the payment algorithm does not always use the Route randomization means the payment algorithm does not always use the
lowest-fee or shortest route\. This prevents some highly-connected node lowest-fee or shortest route\. This prevents some highly-connected node
from learning all of the user payments by reducing their fees below the from learning all of the user payments by reducing their fees below the
network average\. network average\.
Shadow route means the payment algorithm will virtually extend the time 2: Shadow Route
delays along the route, making it appear to intermediate nodes that the
route is longer than it actually is\. This prevents intermediate nodes
from reliably guessing their distance from the payee\. Shadow route means the payment algorithm will virtually extend the route
by adding delays and fees along it, making it appear to intermediate nodes
that the route is longer than it actually is\. This prevents intermediate
nodes from reliably guessing their distance from the payee\.
Route randomization will never exceed \fImaxfeepercent\fR of the payment\. Route randomization will never exceed \fImaxfeepercent\fR of the payment\.
@ -84,6 +84,7 @@ You can monitor the progress and retries of a payment using the
The following error codes may occur: The following error codes may occur:
.RS
.IP \[bu] .IP \[bu]
-1: Catchall nonspecific error\. -1: Catchall nonspecific error\.
.IP \[bu] .IP \[bu]
@ -109,6 +110,7 @@ invoice expiration) as UNIX epoch time in seconds\.
.IP \[bu] .IP \[bu]
210: Payment timed out without a payment in progress\. 210: Payment timed out without a payment in progress\.
.RE
Error codes 202 and 204 will only get reported at \fBsendpay\fR; in Error codes 202 and 204 will only get reported at \fBsendpay\fR; in
\fBpay\fR we will keep retrying if we would have gotten those errors\. \fBpay\fR we will keep retrying if we would have gotten those errors\.
@ -116,6 +118,7 @@ Error codes 202 and 204 will only get reported at \fBsendpay\fR; in
A routing failure object has the fields below: A routing failure object has the fields below:
.RS
.IP \[bu] .IP \[bu]
\fIerring_index\fR: The index of the node along the route that reported \fIerring_index\fR: The index of the node along the route that reported
the error\. 0 for the local node, 1 for the first hop, and so on\. the error\. 0 for the local node, 1 for the first hop, and so on\.
@ -132,6 +135,7 @@ error, or \fI0:0:0\fR if the destination node raised the error\.
received from the remote node\. Only present if error is from the received from the remote node\. Only present if error is from the
remote node and the \fIfailcode\fR has the UPDATE bit set, as per BOLT #4\. remote node and the \fIfailcode\fR has the UPDATE bit set, as per BOLT #4\.
.RE
The \fIdata\fR field of errors will include statistics \fIgetroute_tries\fR and The \fIdata\fR field of errors will include statistics \fIgetroute_tries\fR and
\fIsendpay_tries\fR\. It will also contain a \fIfailures\fR field with detailed \fIsendpay_tries\fR\. It will also contain a \fIfailures\fR field with detailed
@ -150,7 +154,3 @@ Rusty Russell \fI<rusty@rustcorp.com.au\fR> is mainly responsible\.
Main web site: \fIhttps://github.com/ElementsProject/lightning\fR Main web site: \fIhttps://github.com/ElementsProject/lightning\fR
.HL
Last updated 2019-08-01 14:59:36 CEST

View File

@ -48,17 +48,17 @@ randomization.
1: Route Randomization 1: Route Randomization
2: Shadow Route
Route randomization means the payment algorithm does not always use the Route randomization means the payment algorithm does not always use the
lowest-fee or shortest route. This prevents some highly-connected node lowest-fee or shortest route. This prevents some highly-connected node
from learning all of the user payments by reducing their fees below the from learning all of the user payments by reducing their fees below the
network average. network average.
Shadow route means the payment algorithm will virtually extend the time 2: Shadow Route
delays along the route, making it appear to intermediate nodes that the
route is longer than it actually is. This prevents intermediate nodes Shadow route means the payment algorithm will virtually extend the route
from reliably guessing their distance from the payee. by adding delays and fees along it, making it appear to intermediate nodes
that the route is longer than it actually is. This prevents intermediate
nodes from reliably guessing their distance from the payee.
Route randomization will never exceed *maxfeepercent* of the payment. Route randomization will never exceed *maxfeepercent* of the payment.
Route randomization and shadow routing will not take routes that would Route randomization and shadow routing will not take routes that would

View File

@ -820,25 +820,32 @@ static struct command_result *add_shadow_route(struct command *cmd,
const jsmntok_t *chan, *best = NULL; const jsmntok_t *chan, *best = NULL;
size_t i; size_t i;
u64 sample = 0; u64 sample = 0;
u32 cltv, best_cltv; /* FIXME: Use route_info's cltv_expiry_delta member instead */
u32 cltv_fuzz;
struct route_info *route = tal_arr(NULL, struct route_info, 1);
json_for_each_arr(i, chan, channels) { json_for_each_arr(i, chan, channels) {
struct amount_sat sat; u64 v = pseudorand(UINT64_MAX);
u64 v;
json_to_sat(buf, json_get_member(buf, chan, "satoshis"), &sat);
if (amount_msat_greater_sat(pc->msat, sat))
continue;
/* Don't use if total would exceed 1/4 of our time allowance. */
json_to_number(buf, json_get_member(buf, chan, "delay"), &cltv);
if ((pc->final_cltv + cltv) * 4 > pc->maxdelay)
continue;
v = pseudorand(UINT64_MAX);
if (!best || v > sample) { if (!best || v > sample) {
struct amount_sat sat;
json_to_sat(buf, json_get_member(buf, chan, "satoshis"), &sat);
if (amount_msat_greater_sat(pc->msat, sat))
continue;
/* Don't use if total would exceed 1/4 of our time allowance. */
json_to_number(buf, json_get_member(buf, chan, "delay"),
&cltv_fuzz);
if ((pc->final_cltv + cltv_fuzz) * 4 > pc->maxdelay)
continue;
json_to_number(buf, json_get_member(buf, chan, "base_fee_millisatoshi"),
&route[0].fee_base_msat);
json_to_number(buf, json_get_member(buf, chan, "fee_per_millionth"),
&route[0].fee_proportional_millionths);
best = chan; best = chan;
best_cltv = cltv;
sample = v; sample = v;
} }
} }
@ -850,12 +857,18 @@ static struct command_result *add_shadow_route(struct command *cmd,
return start_pay_attempt(cmd, pc, "Initial attempt"); return start_pay_attempt(cmd, pc, "Initial attempt");
} }
pc->final_cltv += best_cltv; pc->final_cltv += cltv_fuzz;
pc->shadow_dest = json_strdup(pc, buf, pc->shadow_dest = json_strdup(pc, buf,
json_get_member(buf, best, "destination")); json_get_member(buf, best, "destination"));
route_msatoshi(&pc->msat, pc->msat, route, 1);
tal_append_fmt(&pc->ps->shadow, tal_append_fmt(&pc->ps->shadow,
"Added %u cltv delay for shadow to %s. ", "Added %u cltv delay, %u base fee, and %u ppm fee "
best_cltv, pc->shadow_dest); "for shadow to %s.",
cltv_fuzz, route[0].fee_base_msat,
route[0].fee_proportional_millionths,
pc->shadow_dest);
tal_free(route);
return shadow_route(cmd, pc); return shadow_route(cmd, pc);
} }