Skip to content

Add recommendations for receiver-side random delays #1263

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 5 commits into
base: master
Choose a base branch
from

Conversation

tnull
Copy link
Contributor

@tnull tnull commented May 30, 2025

After previous discussions on #1044, the last spec meeting, and Delving, it seems there was agreement from multiple sides that receiver-side delays were preferable to forwarding delays. Here, we propose to add such delays to the spec:

Timing attacks on privacy potentially allow on-path adversaries to determine the destination of an observed payment. To this end, they might merely need to record the time difference between sending update_add_htlc and receiving the corresponding update_{fulfill,fail,fail_malformed}_htlc response to be able to guess their distance to the destination and potentially deanonymize the latter.

To counteract this, different implementations previously implemented a variety of mitigation, most commonly adding some kind of (at times randomized) delays when forwarding HTLCs. However, here we propose to instead (or additionally, if the implementations prefer) add a receiver-side delay before claiming or failing HTLCs, which puts the
receiver's privacy improvements in their own hands. Additionally, adding a randomized delay on the receiver's end makes it easier to argue about how much delay should be added to somewhat reliably increase the anonymity set, as previously multiple intermediate hops (or none) could potentially add forwarding delays, which made picking a reasonable per-hop median delay rather hard.

In the second commit, we add similar recommendations to the BOLT12 flow, which might be a bit more controversial.

(cc @joostjager @t-bast @carlaKC @GeorgeTsagk)

Timing attacks on privacy potentially allow on-path adversaries to
determine the destination of an observed payment. To this end, they
might merely need to record the time difference between sending
`update_add_htlc` and receiving the corresponding
`update_{fulfill,fail,fail_malformed}_htlc` response to be able to guess
their distance to the destination and potentially deanonymize the
latter.

To counteract this, different implementations previously implemented a
variety of mitigation, most commonly adding some kind of (at times
randomized) delays when *forwarding* HTLCs. However, here we propose to
instead (or additionally, if the implementations prefer) add a
receiver-side delay before claiming or failing HTLCs, which puts the
receiver's privacy improvements in their own hands. Additionally, adding
a randomized delay on the receiver's end makes it easier to argue about
how much delay should be added to somewhat reliably increase the
anonymity set, as previously multiple intermediate hops (or
none) could potentially add forwarding delays, which made picking a
reasonable per-hop median delay rather hard.
@tnull tnull marked this pull request as draft May 30, 2025 12:27
Copy link
Collaborator

@t-bast t-bast left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Concept ACK.

I'm not sure how we would choose the range used for the random delay though. It seems to me that since malicious nodes trying to do timing analysis would assume that the final hop adds a random delay, it would only work if we add a delay that is potentially much greater than the latency of the whole route (otherwise attacker could just "shift" their guess by a couple of expected hop latency)?

If we assume for example that each hop should take under 100ms in most cases, and we think routes are around 6 hops at most, would it be a good choice to use a delay that is randomly chosen between 600ms and 1800ms?

Copy link
Contributor

@carlaKC carlaKC left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

cACK

hops as input for their routing algorithm should exclude the final hop from
such scoring, to account for the receiver-induced delay (see [BOLT
#2](02-peer-protocol.md#removing-an-htlc-update_fulfill_htlc-update_fail_htlc-and-update_fail_malformed_htlc)).

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we also add a recommendation to introduce a retry delay or make sure to use different paths when retrying a path? Perhaps adding to the timing analysis note in bolt 04.

(maybe this exists, I just grepped for delay + retry and couldn't find it)

Copy link
Contributor Author

@tnull tnull Jun 6, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think adding sender-side delays is necessary, as generally for most nodes it makes a lot of sense to avoid previously-failed paths on retry. I think LND is the only exception to this as it still employs some carve-outs for nodes that respond with one of a specific set of failure codes. As we showed in the paper this behavior is exploitable and likely should be dropped, but I don't know if we need to add a recommendation/requirement for that?

@tnull
Copy link
Contributor Author

tnull commented Jun 2, 2025

I'm not sure how we would choose the range used for the random delay though. It seems to me that since malicious nodes trying to do timing analysis would assume that the final hop adds a random delay, it would only work if we add a delay that is potentially much greater than the latency of the whole route (otherwise attacker could just "shift" their guess by a couple of expected hop latency)?

No, because the adversary can't know how big the added delay is for the particular payment they want to deanonymize. Depending on how large you want to make the anonymity set, it might be sufficient to on average/media plausibly 'cover' an extended route that is 1-3 hops longer (same idea as adding the CLTV 'shadow route').

In practice that could mean, for example, that you draw the delay from a random distribution with a mean of 100-300ms or so. That could be a normal distribution or it needs to be really simple uniform, but prior related research indicated that something like a log-normal distribution be optimal (in terms of the information-theoric 'degree of anonymity' of Diaz et al.).

It is true though that if the adversary is able to observe an overall latency where the receiver added 0 delay, they learn the real baseline, but that is always an option when the delay is purely additive which will always be the case for receiver-added delays, and might be the biggest drawback of this approach. Note that you don't get around that if you just move the baseline up to 600ms, as the adversary might just learn that lower-bound then.

@tnull tnull marked this pull request as ready for review June 3, 2025 11:54
Copy link

@a-mpch a-mpch left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

cACK

@@ -714,6 +715,7 @@ A writer of an invoice:
`invreq_chain`.
- if the invoice is in response to an `invoice_request`:
- MUST copy all non-signature fields from the invoice request (including unknown fields).
- SHOULD add a random delay before sending the invoice.
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we should add a rationale on this point as reading it from top (this BOLT) it is not easy to get why should be added.
Maybe pointing it out to BOLT 2 rationale or just a sentence.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Now added a brief paragraph to the rationale section.

tnull added 4 commits June 6, 2025 13:02
For similar reasons to the previous commit, we also add recommendations
for inserting random delays to the BOLT12 flow to impair timing analysis
capabilities.
@tnull tnull force-pushed the 2025-05-add-delay-recommendations branch from cb8b7b1 to 047da4f Compare June 6, 2025 11:18
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants